Full Code of DaPigGuy/PiggyCustomEnchants for AI

master 7eaf921d3ecd cached
125 files
304.9 KB
82.9k tokens
461 symbols
1 requests
Download .txt
Showing preview only (341K chars total). Download the full file or copy to clipboard to get everything.
Repository: DaPigGuy/PiggyCustomEnchants
Branch: master
Commit: 7eaf921d3ecd
Files: 125
Total size: 304.9 KB

Directory structure:
gitextract_jrwncx0y/

├── .gitattributes
├── .github/
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── crash.md
│   │   ├── outdated_api.md
│   │   ├── suggestion.md
│   │   └── support.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .poggit.yml
├── LICENSE
├── README.md
├── phpstan.neon.dist
├── plugin.yml
├── resources/
│   ├── chances.json
│   ├── config.yml
│   └── descriptions.json
└── src/
    └── DaPigGuy/
        └── PiggyCustomEnchants/
            ├── CustomEnchantManager.php
            ├── EventListener.php
            ├── PiggyCustomEnchants.php
            ├── blocks/
            │   └── PiggyObsidian.php
            ├── commands/
            │   ├── CustomEnchantsCommand.php
            │   └── subcommands/
            │       ├── AboutSubCommand.php
            │       ├── EnchantSubCommand.php
            │       ├── InfoSubCommand.php
            │       ├── ListSubCommand.php
            │       ├── NBTSubCommand.php
            │       └── RemoveSubCommand.php
            ├── enchants/
            │   ├── CustomEnchant.php
            │   ├── CustomEnchantIds.php
            │   ├── ReactiveEnchantment.php
            │   ├── TickingEnchantment.php
            │   ├── ToggleableEnchantment.php
            │   ├── armor/
            │   │   ├── AntiKnockbackEnchant.php
            │   │   ├── ArmoredEnchant.php
            │   │   ├── AttackerDeterrentEnchant.php
            │   │   ├── BerserkerEnchant.php
            │   │   ├── CactusEnchant.php
            │   │   ├── CloakingEnchant.php
            │   │   ├── EndershiftEnchant.php
            │   │   ├── EnlightedEnchant.php
            │   │   ├── ForcefieldEnchant.php
            │   │   ├── GrowEnchant.php
            │   │   ├── HeavyEnchant.php
            │   │   ├── MoltenEnchant.php
            │   │   ├── OverloadEnchant.php
            │   │   ├── PoisonousCloudEnchant.php
            │   │   ├── ReviveEnchant.php
            │   │   ├── SelfDestructEnchant.php
            │   │   ├── ShieldedEnchant.php
            │   │   ├── ShrinkEnchant.php
            │   │   ├── TankEnchant.php
            │   │   ├── boots/
            │   │   │   ├── JetpackEnchant.php
            │   │   │   ├── MagmaWalkerEnchant.php
            │   │   │   └── StompEnchantment.php
            │   │   ├── chestplate/
            │   │   │   ├── ChickenEnchant.php
            │   │   │   ├── ParachuteEnchant.php
            │   │   │   ├── ProwlEnchant.php
            │   │   │   ├── SpiderEnchant.php
            │   │   │   └── VacuumEnchant.php
            │   │   └── helmet/
            │   │       ├── AntitoxinEnchant.php
            │   │       ├── FocusedEnchant.php
            │   │       ├── ImplantsEnchant.php
            │   │       └── MeditationEnchant.php
            │   ├── miscellaneous/
            │   │   ├── AutoRepairEnchant.php
            │   │   ├── LuckyCharmEnchant.php
            │   │   ├── RadarEnchant.php
            │   │   ├── RecursiveEnchant.php
            │   │   ├── SoulboundEnchant.php
            │   │   └── ToggleableEffectEnchant.php
            │   ├── tools/
            │   │   ├── DrillerEnchant.php
            │   │   ├── EnergizingEnchant.php
            │   │   ├── ExplosiveEnchant.php
            │   │   ├── QuickeningEnchant.php
            │   │   ├── SmeltingEnchant.php
            │   │   ├── TelepathyEnchant.php
            │   │   ├── axes/
            │   │   │   └── LumberjackEnchant.php
            │   │   ├── hoe/
            │   │   │   ├── FarmerEnchant.php
            │   │   │   ├── FertilizerEnchant.php
            │   │   │   └── HarvestEnchant.php
            │   │   └── pickaxe/
            │   │       └── JackpotEnchant.php
            │   ├── traits/
            │   │   ├── ReactiveTrait.php
            │   │   ├── TickingTrait.php
            │   │   └── ToggleTrait.php
            │   └── weapons/
            │       ├── BlessedEnchant.php
            │       ├── ConditionalDamageMultiplierEnchant.php
            │       ├── DeathbringerEnchant.php
            │       ├── DeepWoundsEnchant.php
            │       ├── DisarmingEnchant.php
            │       ├── DisarmorEnchant.php
            │       ├── GooeyEnchant.php
            │       ├── HallucinationEnchant.php
            │       ├── LacedWeaponEnchant.php
            │       ├── LifestealEnchant.php
            │       ├── LightningEnchant.php
            │       ├── VampireEnchant.php
            │       └── bows/
            │           ├── AutoAimEnchant.php
            │           ├── BombardmentEnchant.php
            │           ├── BountyHunterEnchant.php
            │           ├── GrapplingEnchant.php
            │           ├── HeadhunterEnchant.php
            │           ├── HealingEnchant.php
            │           ├── MissileEnchant.php
            │           ├── MolotovEnchant.php
            │           ├── ParalyzeEnchant.php
            │           ├── PiercingEnchant.php
            │           ├── ProjectileChangingEnchant.php
            │           ├── ShuffleEnchant.php
            │           └── VolleyEnchant.php
            ├── entities/
            │   ├── BombardmentTNT.php
            │   ├── HomingArrow.php
            │   ├── PigProjectile.php
            │   ├── PiggyFireball.php
            │   ├── PiggyLightning.php
            │   ├── PiggyProjectile.php
            │   ├── PiggyTNT.php
            │   └── PiggyWitherSkull.php
            ├── particles/
            │   └── JetpackParticle.php
            ├── tasks/
            │   ├── CheckDisabledEnchantsTask.php
            │   └── TickEnchantmentsTask.php
            └── utils/
                ├── AllyChecks.php
                ├── PiggyExplosion.php
                ├── ProjectileTracker.php
                └── Utils.php

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto

# Custom for Visual Studio
*.cs     diff=csharp

# Standard to msysgit
*.doc	 diff=astextplain
*.DOC	 diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot  diff=astextplain
*.DOT  diff=astextplain
*.pdf  diff=astextplain
*.PDF	 diff=astextplain
*.rtf	 diff=astextplain
*.RTF	 diff=astextplain


================================================
FILE: .github/CONTRIBUTING.md
================================================
# PiggyCustomEnchants

## Contribution Guidelines

### Issues
If you are submitting an issue ticket, you must:
* Must be PMMP w/o vanilla patching plugins (i.e. TeaSpoon)
* Issue must have not been reported previously
* Must be on latest version of PMMP & PiggyCustomEnchants
* Have a detailed title.
* If possible, provide crashdumps/errors related to the issue.

### Pull Requests
If you are submitting a pull request, you must:
* Use same formatting
* Changes must have been tested on PMMP.
* Unless it is a minor code modification, you must use an IDE.
* Have a detailed title, like "Fix Poison enchant does not apply effect"

<i>Last updated: Sunday, March 15, 2020.</i>

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug Report
about: Unexpected non-crash behavior with PiggyCustomEnchants
title: ''
labels: 'Type: Bug'
assignees: 'DaPigGuy'
---

<!-- Failure to complete the required fields will result in the issue being closed. -->
Please make sure your issue complies with these guidelines:
- * [ ] Server Software must be the official PMMP w/o vanilla patching plugins (i.e. TeaSpoon)
- * [ ] Issue must have not been reported previously
- * [ ] Make sure you are on the latest version of PMMP & PiggyCustomEnchants
- * [ ] Have a detailed title.

### Issue Description

- Expected result: What were you expecting to happen?
- Actual result: What actually happened?

#### Steps to Reproduce the Issue
1. ...
2. ...

### OS and Versions
<!-- Use `/version` for PMMP version & `/version PiggyCustomEnchants` for PiggyCustomEnchants version -->
* PocketMine-MP:
* PiggyCustomEnchants:
* PHP:
* Server OS:

<!--- Provide any extra information below  -->
### Extra Information

================================================
FILE: .github/ISSUE_TEMPLATE/crash.md
================================================
---
name: Crash
about: Report a crash in PiggyCustomEnchants
title: ''
labels: 'Type: Bug'
assignees: 'DaPigGuy'
---

<!-- Failure to complete the required fields will result in the issue being closed. -->

Please make sure your issue complies with these guidelines:
- * [ ] Server Software must be the official PMMP w/o vanilla patching plugins (i.e. TeaSpoon)
- * [ ] Issue must have not been reported previously
- * [ ] Make sure you are on the latest version of PMMP & PiggyCustomEnchants
- * [ ] Have a detailed title.

<!--- Submit crash dumps to https://crash.pmmp.io or copy & paste contents to https://hastebin.com -->
Link to crashdump: 

<!--- Provide any extra information below  -->
### Extra Information

================================================
FILE: .github/ISSUE_TEMPLATE/outdated_api.md
================================================
---
name: Outdated API Version
about: Please do not create an issue for this. The plugin will be updated to the latest PMMP version as soon as possible.
title: 'Outdated API Version'
labels: 'Resolution: Invalid'
assignees: ''
---

Please do not create an issue. Doing so will only delay an update.

================================================
FILE: .github/ISSUE_TEMPLATE/suggestion.md
================================================
---
name: Feature Suggestion
about: Suggest features you would like added to PiggyCustomEnchants
title: ''
labels: 'Type: Enhancement'
assignees: 'DaPigGuy'
---

<!-- Failure to complete the required fields will result in the issue being closed. -->
Please make sure your issue complies with these guidelines:
- * [ ] Idea must have not been suggested previously
- * [ ] Be detailed on what you want & make sure the idea is plausible

### Description
<!-- Describe your idea in detail below -->

### Extra Information

================================================
FILE: .github/ISSUE_TEMPLATE/support.md
================================================
---
name: Support
about: Please do not create an issue for this. Join our Discord for support (link in README).
title: ''
labels: 'Resolution: Invalid'
assignees: ''
---

Please do not create an issue for this. Join our Discord for support (link in README).

================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!-- Failure to complete the required fields will result in the issue being closed. -->
Please make sure your pull request complies with these guidelines:
- * [ ] Use same formatting
- * [ ] Changes must have been tested on PMMP.
- * [ ] Unless it is a minor code modification, you must use an IDE.
- * [ ] Have a detailed title.

#### **What does the PR change?**
<!-- 
Does your Pull Request:
- resolve a bug? If so, link the issue with the PR and add explain what caused the issue.
- enhance the plugin? If so, explain what this adds, including why it should be added.
-->

#### **Testing Environment**
<!-- PHP and OS version required, pmmp build link required. -->
- PHP: 
- PMMP:
- OS:

#### **Extra Information**
<!-- Anything else we should know? -->


================================================
FILE: .github/workflows/main.yml
================================================
name: PHPStan

on:
  push:
    branches:
      - master
  pull_request:

jobs:
  phpstan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          ref: ${{ github.ref }}
      - name: Create Vendor Directory
        run: mkdir vendor
      - name: Download Virion Dependencies
        run: |
          wget -O vendor/libFormAPI.phar https://poggit.pmmp.io/r/207248/libFormAPI_dev-4.phar
          wget -O vendor/Commando.phar https://poggit.pmmp.io/r/162923/Commando_dev-30.phar
          wget -O vendor/libPiggyUpdateChecker.phar https://poggit.pmmp.io/r/163495/libPiggyUpdateChecker_dev-1.phar
      - name: Run PHPStan
        uses: paroxity/pmmp-phpstan-action@4.21.0
        with:
          phpstan-config: phpstan.neon.dist


================================================
FILE: .gitignore
================================================
# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk

# JetBrains IDE
\.idea
\.dependencies

================================================
FILE: .poggit.yml
================================================
--- # Poggit-CI Manifest. Open the CI at https://poggit.pmmp.io/ci/DaPigGuy/PiggyCustomEnchants
branches:
  - master
  - pmmp-4.0.0
projects:
  PiggyCustomEnchants:
    path: ""
    icon: "resources/PCE_Icon.png"
    libs:
      - src: jojoe77777/FormAPI/libFormAPI
        version: ^2.1.1
      - src: Paroxity/Commando/Commando
        version: ^3.0.0
      - src: DaPigGuy/libPiggyUpdateChecker/libPiggyUpdateChecker
        version: ^1.0.0
    lint: false
...

================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright 2017 DaPigGuy

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
# PiggyCustomEnchants [![Poggit-CI](https://poggit.pmmp.io/shield.dl/PiggyCustomEnchants)](https://poggit.pmmp.io/p/PiggyCustomEnchants) [![Discord](https://img.shields.io/discord/330850307607363585?logo=discord)](https://discord.gg/qmnDsSD)

PiggyCustomEnchants is an open-sourced custom enchants plugin for [PocketMine-MP](https://github.com/pmmp/PocketMine-MP) featuring over 90 custom enchantments.

<!-- If one question constantly persists, add the Q/A in here. -->
## FAQ
**Q:** How do I create/use an enchanted book? </br>
**A:** If you want to create an enchanted book, use the /ce enchant command on a normal book. Afterwards, you place the item you want to enchant on top of the enchanted book. It will then enchant your item.

## Prerequisites
* Basic knowledge on how to install plugins from Poggit Releases and/or Poggit CI
* PMMP 4.21.0+

## Installation & Setup
1. Install the plugin from Poggit.
2. (Optional) Configure your PiggyCE
   * Enchantment rarities, max levels, names, descriptions, & chances can be configured in their respective JSON files.
        * `chances.json`: Allows custom chance multipliers for any reactive enchantments.
            * Reaction chances are calculated by `chance multiplier * enchantment level`.
            * The chance multiplier by default is 100 for most enchantments.
   * Extra enchantment settings can be found under `extra_data.json`
   * The `config.yml` has many options. Some that you should pay attention to are:
     * `disabled-enchants`: Allows certain enchants to be disabled
     
         ```yaml
            disabled-enchants:
              - Porkified
         ```
     * `per-world-disabled-enchants`: Allows certain enchants to be disabled in specific worlds
     
         ```yaml
            per-world-disabled-enchants:
              # Disables Porkified & Volley in PlotWorld
              PlotWorld:
                - Porkified
                - Volley
              # Disables Jetpack in SurvivalWorld
              SurvivalWorld:
                - Jetpack
         ```
     * `world-damage`: Toggles world damage for explosive enchantments
3. (Optional) Install additional plugins supporting PiggyCE:
   * [PiggyCrates](https://poggit.pmmp.io/p/PiggyCrates) (Official)
   * [PiggyCustomEnchantsShop](https://poggit.pmmp.io/p/PiggyCustomEnchantsShop) (Official)
   * [PCEAllyChecks](https://poggit.pmmp.io/p/PCEAllyChecks) (Official)
   * [PCEBookShop](https://poggit.pmmp.io/p/PCEBookShop) (Official)
   * Kits
      * [EasyKits](https://poggit.pmmp.io/p/EasyKits)
      * [AdvancedKits](https://poggit.pmmp.io/p/AdvancedKits) 
      * [KitUI](https://poggit.pmmp.io/p/KitUI)
      * [KitsPlus](https://poggit.pmmp.io/p/KitsPlus)
   * [EnchantUI](https://poggit.pmmp.io/p/EnchantUI)
5. You're done! Start your server.

## Commands
| Command                  | Description                                     | Permissions                              | Aliases       |
|--------------------------|-------------------------------------------------|------------------------------------------|---------------|
| `/customenchant`         | Main command for PiggyCustomEnchants            | `piggycustomenchants.command.ce`         | `/ce`         |
| `/customenchant about`   | Shows version and author information            | `piggycustomenchants.command.ce.about`   | `/ce about`   |
| `/customenchant enchant` | Command to enchant an item with custom enchants | `piggycustomenchants.command.ce.enchant` | `/ce enchant` |
| `/customenchant help`    | Lists all PiggyCustomEnchant commands           | `piggycustomenchants.command.ce.help`    | `/ce help`    |
| `/customenchant info`    | Gives information on a custom enchant           | `piggycustomenchants.command.ce.info`    | `/ce info`    |
| `/customenchant list`    | Lists all PiggyCustomEnchants enchants          | `piggycustomenchants.command.ce.list`    | `/ce list`    |
| `/customenchant nbt`     | Outputs the NBT of the held item                | `piggycustomenchants.command.ce.nbt`     | `/ce nbt`     |
| `/customenchant remove`  | Removes a custom enchant from the held item     | `piggycustomenchants.command.ce.remove`  | `/ce remove`  |

## Permissions
| Permissions                              | Description                                                         | Default |
|------------------------------------------|---------------------------------------------------------------------|---------|
| `piggycustomenchants`                    | Allows usage of all PiggyCustomEnchants features                    | `op`    |
| `piggycustomenchants.command`            | Allow usage of all PiggyCustomEnchants commands                     | `op`    |
| `piggycustomenchants.command.ce`         | Allow usage of the /customenchant command                           | `op`    |
| `piggycustomenchants.command.ce.about`   | Allow usage of the /customenchant about subcommand                  | `true`  |
| `piggycustomenchants.command.ce.enchant` | Allow usage of the /customenchant enchant subcommand                | `op`    |
| `piggycustomenchants.command.ce.help`    | Allow usage of the /customenchant help subcommand                   | `true`  |
| `piggycustomenchants.command.ce.info`    | Allow usage of the /customenchant info subcommand                   | `true`  |
| `piggycustomenchants.command.ce.list`    | Allow usage of the /customenchant list subcommand                   | `true`  |
| `piggycustomenchants.command.ce.nbt`     | Allow usage of the /customenchant nbt subcommand                    | `true`  |
| `piggycustomenchants.command.ce.remove`  | Allow usage of the /customenchant remove subcommand                 | `op`    |
| `piggycustomenchants.overridecheck`      | Allow overriding of custom enchant level limit and item restriction | `false` |

## Issue Reporting
* If you experience an unexpected non-crash behavior with PiggyCustomEnchants, click [here](https://github.com/DaPigGuy/PiggyCustomEnchants/issues/new?assignees=DaPigGuy&labels=bug&template=bug_report.md&title=).
* If you experience a crash in PiggyCustomEnchants, click [here](https://github.com/DaPigGuy/PiggyCustomEnchants/issues/new?assignees=DaPigGuy&labels=bug&template=crash.md&title=).
* If you would like to suggest a feature to be added to PiggyCustomEnchants, click [here](https://github.com/DaPigGuy/PiggyCustomEnchants/issues/new?assignees=DaPigGuy&labels=suggestion&template=suggestion.md&title=).
* If you require support, please join our discord server [here](https://discord.gg/qmnDsSD).
* Do not file any issues related to outdated API version; we will resolve such issues as soon as possible.
* We do not support any spoons of PocketMine-MP. Anything to do with spoons (Issues or PRs) will be ignored.
  * This includes plugins that modify PocketMine-MP's behavior directly, such as TeaSpoon.

## Additional Information
* Detailed Plugin Setup, Custom Enchantment List, & API Documentation available at [PiggyDocs](https://piggydocs.aericio.net/PiggyCustomEnchants.html).

## License
```
   Copyright 2017 DaPigGuy

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

```


================================================
FILE: phpstan.neon.dist
================================================
parameters:
  paths:
    - /source/src
  level: 7
  bootstrapFiles:
    - phar:///pocketmine/PocketMine-MP.phar/vendor/autoload.php
  scanDirectories:
    - phar:///source/vendor/libFormAPI.phar/src/
    - phar:///source/vendor/Commando.phar/src/
    - phar:///source/vendor/libPiggyUpdateChecker.phar/src/
  excludePaths:
    analyse:
      - source/vendor
  checkMissingIterableValueType: false
  ignoreErrors:
    - "#Strict comparison using === between pocketmine\\\\inventory\\\\PlayerInventory and null will always evaluate to false.#"

================================================
FILE: plugin.yml
================================================
name: PiggyCustomEnchants
main: DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants
version: 3.0.12
api: 4.21.0
load: POSTWORLD
author: DaPigGuy
website: "https://github.com/DaPigGuy/PiggyCustomEnchants/"
permissions:
  piggycustomenchants:
    default: false
    description: "Allows usage of all PiggyCustomEnchants features"
  piggycustomenchants.command:
    default: op
    description: "Allow usage of all PiggyCustomEnchants commands"
  piggycustomenchants.command.ce:
    default: op
    description: "Allow usage of the /customenchant command"
  piggycustomenchants.command.ce.about:
    default: true
    description: "Allow usage of the /customenchant about subcommand"
  piggycustomenchants.command.ce.enchant:
    default: op
    description: "Allow usage of the /customenchant enchant subcommand"
  piggycustomenchants.command.ce.help:
    default: true
    description: "Allow usage of the /customenchant help subcommand"
  piggycustomenchants.command.ce.info:
    default: true
    description: "Allow usage of the /customenchant info subcommand"
  piggycustomenchants.command.ce.list:
    default: true
    description: "Allow usage of the /customenchant list subcommand"
  piggycustomenchants.command.ce.nbt:
    default: true
    description: "Allow usage of the /customenchant nbt subcommand"
  piggycustomenchants.command.ce.remove:
    default: op
    description: "Allow usage of the /customenchant remove subcommand"
  piggycustomenchants.overridecheck:
    default: false
    description: "Allow overriding of custom enchant level limit and item restriction"


================================================
FILE: resources/chances.json
================================================
{
  "blessed": 15,
  "deepwounds": 20,
  "disarmor": 10,
  "disarming": 10,
  "hallucination": 5,
  "jackpot": 10,
  "lightning": 10
}

================================================
FILE: resources/config.yml
================================================
# Specifies the color enchants are shown depending on rarity
# Options: black, dark_blue, dark_green, dark_aqua, dark_red, dark_purple, gold, gray, dark_gray, blue, green, aqua, red, light_purple, yellow, and white
rarity-colors:
  common: yellow
  uncommon: blue
  rare: gold
  mythic: light_purple
enchants:
  # Specifies the location enchants are shown. Options: name, lore
  position: "name"
  # Toggles roman numerals for displaying enchantment levels
  roman-numerals: true
  # Toggles PiggyCE enchantment books
  books: true
# Toggles forms for /ce command
forms:
  enabled: false
# What enchants to disable ENTIRELY
disabled-enchants: []
# What enchants to disable in specific worlds
per-world-disabled-enchants:
  NoJetpackWorld:
    - "jetpack"
# If enabled, will check a list of extremely problematic enchantments on your version of the plugin to be disabled
# We will ONLY remotely disable enchantments that are extremely problematic / major exploits and this functionality will not be abused in any way
# Please update your plugin to the latest version (if available) if an enchantment on your version was disabled
# Gist: https://gist.github.com/DaPigGuy/9c65a998bc0aa8d6b4708796110f7d11
remote-disable: true
# Whether or not an enchant damages world
world-damage:
  blaze: true
  bombardment: true
  lightning: true
  missile: true
  self-destruct: true

================================================
FILE: resources/descriptions.json
================================================
{
  "antiknockback": "Reduces knockback per armor piece.",
  "antitoxin": "Grants immunity to poison.",
  "aerial": "While in air, damage increases.",
  "armored": "Sword-inflicted damage is reduced.",
  "autoaim": "Automatically aims to the nearest target.",
  "autorepair": "Items automatically repair while moving.",
  "backstab": "Backstabbing enemies deals increased damage.",
  "berserker": "Gain strength when low on health.",
  "blessed": "Grants a chance to remove harmful effects during combat.",
  "blaze": "Shoots blazing fireballs.",
  "blind": "Inflicts Blindness upon hitting enemies.",
  "bombardment": "Bombard enemies with TNT when shot.",
  "bountyhunter": "Grants chance to obtain treasure from hitting enemies.",
  "cactus": "Deal damage to nearby enemies.",
  "charge": "Damage increases while sprinting.",
  "chicken": "Lay eggs every 5 minutes with a chance of rare drop.",
  "cloaking": "Gain invisibility when hit.",
  "cripple": "Inflicts Nausea and Slowness upon hitting enemy.",
  "cursed": "Inflicts Wither upon hitting enemy.",
  "deathbringer": "Increases damage inflicted.",
  "deepwounds": "Inflict on enemies deep wounds that cause bleeding.",
  "disarming": "Grants chance to disarm enemy.",
  "disarmor": "Grants chance to disarmor enemy.",
  "driller": "Drills a 3 by 3 hole.",
  "drunk": "Inflicts Slowness, Mining Fatigue, and Nausea upon hitting enemy.",
  "endershift": "Gain Speed and Absorption when low on health.",
  "energizing": "Gain Haste when a block is broken.",
  "enlighted": "Gain Regeneration when hit.",
  "enraged": "Gain Strength while equipped.",
  "explosive": "Causes an explosion when a block is broken.",
  "farmer": "Automatically replaces seeds when crop is broken.",
  "fertilizer": "Tills land in a radius dependent on enchantment level.",
  "focused": "Negates or reduces the effects of nausea.",
  "forcefield": "Deflects projectiles and living entities in a radius dependent on enchantment level.",
  "frozen": "Inflicts Slowness upon hitting enemy.",
  "gears": "Gain Speed while equipped.",
  "glowing": "Gain Night Vision while equipped.",
  "gooey": "Flings enemy into the air.",
  "grappling": "Pulls you to the arrow. If enemy is hit, the enemy will be pulled to you.",
  "grow": "Increases size on sneak (Must be wearing full set of Grow armor).",
  "hallucination": "Grants chance of trapping enemies in a fake prison.",
  "hardened": "Inflicts Weakness upon hitting enemy.",
  "haste": "Gain Haste while tool is held.",
  "harvest": "Harvest crops in a radius dependent on enchantment level.",
  "headhunter": "Headshots deal more damage.",
  "healing": "Heals target for inflicted damage + extra health.",
  "heavy": "Bow-inflicted damage is reduced.",
  "homing": "Arrow will home in on the nearest entity.",
  "implants": "Replenishes hunger and air when moving.",
  "jetpack": "Flies in the direction you are facing when you sneak.",
  "jackpot": "Grants chance to increase ore tier.",
  "lifesteal": "Steals health upon hitting enemy.",
  "lightning": "Chance to strike enemies with lightning.",
  "luckycharm": "Increases activation chance of reactive enchantments.",
  "lumberjack": "Breaks all logs connected to each other.",
  "magmawalker": "Temporarily turns lava into obsidian around you.",
  "meditation": "Replenishes health and hunger every 20 seconds when not moving.",
  "missile": "Spawns TNT where arrow lands.",
  "molotov": "Starts a fire where arrow lands.",
  "molten": "Sets an enemy on fire when hit.",
  "obsidianshield": "Gain Fire Resistance while equipped.",
  "overload": "Gives extra health (stackable).",
  "oxygenate": "Gain Water Breathing while item is held.",
  "parachute": "Slows your descent above 3 blocks.",
  "paralyze": "Inflicts Slowness, Blindness, and Weakness upon hitting enemies.",
  "piercing": "Ignores armor when dealing damage.",
  "poison": "Inflicts Poison upon hitting enemies.",
  "poisonouscloud": "Creates a cloud of poison around entity, giving poison to anyone who enters.",
  "poisoned": "Inflicts Poison when hit by an enemy.",
  "porkified": "Oink! Shoots pigs, leaving a mysterious pork behind when killed.",
  "prowl": "Gain Invisibility and Slowness while sneaking.",
  "quickening": "Gain Speed for upon breaking block.",
  "radar": "Points towards the nearest player.",
  "revive": "Gain another life, but removes a level from armor.",
  "revulsion": "Inflicts Nausea for when hit by an enemy.",
  "selfdestruct": "Spawns TNT when you die.",
  "shielded": "Gives Resistance while worn (stackable).",
  "shrink": "Decreases size on sneak (Must be wearing full set of Shrink armor).",
  "shuffle": "Switches position with target.",
  "smelting": "Automatically smelts drop when block is broken.",
  "soulbound": "Keeps item after death, but removes a level from armor.",
  "spider": "Ability to climb walls.",
  "springs": "Gain a small jump boost.",
  "stomp": "Deal damage to enemy when taking fall damage.",
  "tank": "Decreases damage from axes.",
  "telepathy": "Automatically puts drops into inventory.",
  "vacuum": "Suck up nearby items.",
  "vampire": "Converts damage dealt into health.",
  "volley": "Shoots multiple arrows in a cone shape.",
  "wither": "Inflicts Wither on enemies.",
  "witherskull": "Shoots wither skulls."
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/CustomEnchantManager.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants;

use DaPigGuy\PiggyCustomEnchants\enchants\armor\AntiKnockbackEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\ArmoredEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\AttackerDeterrentEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\BerserkerEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\boots\JetpackEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\boots\MagmaWalkerEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\boots\StompEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\CactusEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\chestplate\ChickenEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\chestplate\ParachuteEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\chestplate\ProwlEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\chestplate\SpiderEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\chestplate\VacuumEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\CloakingEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\EndershiftEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\EnlightedEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\ForcefieldEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\GrowEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\HeavyEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\helmet\AntitoxinEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\helmet\FocusedEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\helmet\ImplantsEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\helmet\MeditationEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\MoltenEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\OverloadEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\PoisonousCloudEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\ReviveEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\SelfDestructEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\ShieldedEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\ShrinkEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\TankEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous\AutoRepairEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous\LuckyCharmEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous\RadarEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous\SoulboundEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous\ToggleableEffectEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\axes\LumberjackEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\DrillerEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\EnergizingEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\ExplosiveEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\hoe\FarmerEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\hoe\FertilizerEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\hoe\HarvestEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\pickaxe\JackpotEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\QuickeningEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\SmeltingEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\TelepathyEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\BlessedEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\AutoAimEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\BombardmentEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\BountyHunterEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\GrapplingEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\HeadhunterEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\HealingEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\MissileEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\MolotovEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\ParalyzeEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\PiercingEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\ProjectileChangingEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\ShuffleEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\bows\VolleyEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\ConditionalDamageMultiplierEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\DeathbringerEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\DeepWoundsEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\DisarmingEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\DisarmorEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\GooeyEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\HallucinationEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\LacedWeaponEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\LifestealEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\LightningEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\weapons\VampireEnchant;
use DaPigGuy\PiggyCustomEnchants\entities\HomingArrow;
use DaPigGuy\PiggyCustomEnchants\entities\PiggyFireball;
use DaPigGuy\PiggyCustomEnchants\entities\PiggyWitherSkull;
use DaPigGuy\PiggyCustomEnchants\entities\PigProjectile;
use pocketmine\data\bedrock\EnchantmentIdMap;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\entity\Living;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\enchantment\StringToEnchantmentParser;
use pocketmine\utils\StringToTParser;
use ReflectionProperty;

class CustomEnchantManager
{
    private static PiggyCustomEnchants $plugin;

    /** @var CustomEnchant[] */
    public static array $enchants = [];

    public static function init(PiggyCustomEnchants $plugin): void
    {
        self::$plugin = $plugin;

        self::registerEnchantment(new AttackerDeterrentEnchant($plugin, CustomEnchantIds::CURSED, "Cursed", [VanillaEffects::WITHER()], [60], [1], Rarity::UNCOMMON));
        self::registerEnchantment(new AttackerDeterrentEnchant($plugin, CustomEnchantIds::DRUNK, "Drunk", [VanillaEffects::SLOWNESS(), VanillaEffects::MINING_FATIGUE(), VanillaEffects::NAUSEA()], [60, 60, 60], [1, 1, 0]));
        self::registerEnchantment(new AttackerDeterrentEnchant($plugin, CustomEnchantIds::FROZEN, "Frozen", [VanillaEffects::SLOWNESS()], [60], [1]));
        self::registerEnchantment(new AttackerDeterrentEnchant($plugin, CustomEnchantIds::HARDENED, "Hardened", [VanillaEffects::WEAKNESS()], [60], [1], Rarity::UNCOMMON));
        self::registerEnchantment(new AttackerDeterrentEnchant($plugin, CustomEnchantIds::POISONED, "Poisoned", [VanillaEffects::POISON()], [60], [1], Rarity::UNCOMMON));
        self::registerEnchantment(new AttackerDeterrentEnchant($plugin, CustomEnchantIds::REVULSION, "Revulsion", [VanillaEffects::NAUSEA()], [20], [0], Rarity::UNCOMMON));

        self::registerEnchantment(new ConditionalDamageMultiplierEnchant($plugin, CustomEnchantIds::AERIAL, "Aerial", fn(EntityDamageByEntityEvent $event) => !$event->getDamager()?->isOnGround(), Rarity::UNCOMMON));
        self::registerEnchantment(new ConditionalDamageMultiplierEnchant($plugin, CustomEnchantIds::BACKSTAB, "Backstab", fn(EntityDamageByEntityEvent $event) => $event->getDamager()?->getDirectionVector()->dot($event->getEntity()->getDirectionVector()) > 0, Rarity::UNCOMMON));
        self::registerEnchantment(new ConditionalDamageMultiplierEnchant($plugin, CustomEnchantIds::CHARGE, "Charge", fn(EntityDamageByEntityEvent $event) => ($damager = $event->getDamager()) instanceof Living && $damager->isSprinting(), Rarity::UNCOMMON));

        self::registerEnchantment(new LacedWeaponEnchant($plugin, CustomEnchantIds::BLIND, "Blind", Rarity::COMMON, [VanillaEffects::BLINDNESS()], [20], [0], [100]));
        self::registerEnchantment(new LacedWeaponEnchant($plugin, CustomEnchantIds::CRIPPLE, "Cripple", Rarity::COMMON, [VanillaEffects::NAUSEA(), VanillaEffects::SLOWNESS()], [100, 100], [0, 1]));
        self::registerEnchantment(new LacedWeaponEnchant($plugin, CustomEnchantIds::POISON, "Poison", Rarity::UNCOMMON, [VanillaEffects::POISON()]));
        self::registerEnchantment(new LacedWeaponEnchant($plugin, CustomEnchantIds::WITHER, "Wither", Rarity::UNCOMMON, [VanillaEffects::WITHER()]));

        self::registerEnchantment(new ProjectileChangingEnchant($plugin, CustomEnchantIds::BLAZE, "Blaze", PiggyFireball::class));
        self::registerEnchantment(new ProjectileChangingEnchant($plugin, CustomEnchantIds::HOMING, "Homing", HomingArrow::class, 3, Rarity::MYTHIC));
        self::registerEnchantment(new ProjectileChangingEnchant($plugin, CustomEnchantIds::PORKIFIED, "Porkified", PigProjectile::class, 3, Rarity::MYTHIC));
        self::registerEnchantment(new ProjectileChangingEnchant($plugin, CustomEnchantIds::WITHERSKULL, "Wither Skull", PiggyWitherSkull::class, 1, Rarity::MYTHIC));

        self::registerEnchantment(new ToggleableEffectEnchant($plugin, CustomEnchantIds::ENRAGED, "Enraged", 5, CustomEnchant::TYPE_CHESTPLATE, CustomEnchant::ITEM_TYPE_CHESTPLATE, VanillaEffects::STRENGTH(), -1));
        self::registerEnchantment(new ToggleableEffectEnchant($plugin, CustomEnchantIds::GEARS, "Gears", 1, CustomEnchant::TYPE_BOOTS, CustomEnchant::ITEM_TYPE_BOOTS, VanillaEffects::SPEED(), 0, 0, Rarity::UNCOMMON));
        self::registerEnchantment(new ToggleableEffectEnchant($plugin, CustomEnchantIds::GLOWING, "Glowing", 1, CustomEnchant::TYPE_HELMET, CustomEnchant::ITEM_TYPE_HELMET, VanillaEffects::NIGHT_VISION(), 0, 0, Rarity::COMMON));
        self::registerEnchantment(new ToggleableEffectEnchant($plugin, CustomEnchantIds::HASTE, "Haste", 5, CustomEnchant::TYPE_HAND, CustomEnchant::ITEM_TYPE_PICKAXE, VanillaEffects::HASTE(), 0, 1, Rarity::UNCOMMON));
        self::registerEnchantment(new ToggleableEffectEnchant($plugin, CustomEnchantIds::OBSIDIANSHIELD, "Obsidian Shield", 1, CustomEnchant::TYPE_ARMOR_INVENTORY, CustomEnchant::ITEM_TYPE_ARMOR, VanillaEffects::FIRE_RESISTANCE(), 0, 0, Rarity::COMMON));
        self::registerEnchantment(new ToggleableEffectEnchant($plugin, CustomEnchantIds::OXYGENATE, "Oxygenate", 1, CustomEnchant::TYPE_HAND, CustomEnchant::ITEM_TYPE_PICKAXE, VanillaEffects::WATER_BREATHING(), 0, 0, Rarity::UNCOMMON));
        self::registerEnchantment(new ToggleableEffectEnchant($plugin, CustomEnchantIds::SPRINGS, "Springs", 1, CustomEnchant::TYPE_BOOTS, CustomEnchant::ITEM_TYPE_BOOTS, VanillaEffects::JUMP_BOOST(), 3, 0, Rarity::UNCOMMON));

        self::registerEnchantment(new AntiKnockbackEnchant($plugin, CustomEnchantIds::ANTIKNOCKBACK));
        self::registerEnchantment(new AntitoxinEnchant($plugin, CustomEnchantIds::ANTITOXIN));
        self::registerEnchantment(new AutoAimEnchant($plugin, CustomEnchantIds::AUTOAIM));
        self::registerEnchantment(new AutoRepairEnchant($plugin, CustomEnchantIds::AUTOREPAIR));
        self::registerEnchantment(new ArmoredEnchant($plugin, CustomEnchantIds::ARMORED));
        self::registerEnchantment(new BerserkerEnchant($plugin, CustomEnchantIds::BERSERKER));
        self::registerEnchantment(new BlessedEnchant($plugin, CustomEnchantIds::BLESSED));
        self::registerEnchantment(new BombardmentEnchant($plugin, CustomEnchantIds::BOMBARDMENT));
        self::registerEnchantment(new BountyHunterEnchant($plugin, CustomEnchantIds::BOUNTYHUNTER));
        self::registerEnchantment(new CactusEnchant($plugin, CustomEnchantIds::CACTUS));
        self::registerEnchantment(new ChickenEnchant($plugin, CustomEnchantIds::CHICKEN));
        self::registerEnchantment(new CloakingEnchant($plugin, CustomEnchantIds::CLOAKING));
        self::registerEnchantment(new DeathbringerEnchant($plugin, CustomEnchantIds::DEATHBRINGER));
        self::registerEnchantment(new DeepWoundsEnchant($plugin, CustomEnchantIds::DEEPWOUNDS));
        self::registerEnchantment(new DisarmingEnchant($plugin, CustomEnchantIds::DISARMING));
        self::registerEnchantment(new DisarmorEnchant($plugin, CustomEnchantIds::DISARMOR));
        self::registerEnchantment(new DrillerEnchant($plugin, CustomEnchantIds::DRILLER));
        self::registerEnchantment(new EndershiftEnchant($plugin, CustomEnchantIds::ENDERSHIFT));
        self::registerEnchantment(new EnergizingEnchant($plugin, CustomEnchantIds::ENERGIZING));
        self::registerEnchantment(new EnlightedEnchant($plugin, CustomEnchantIds::ENLIGHTED));
        self::registerEnchantment(new ExplosiveEnchant($plugin, CustomEnchantIds::EXPLOSIVE));
        self::registerEnchantment(new FarmerEnchant($plugin, CustomEnchantIds::FARMER));
        self::registerEnchantment(new FertilizerEnchant($plugin, CustomEnchantIds::FERTILIZER));
        self::registerEnchantment(new FocusedEnchant($plugin, CustomEnchantIds::FOCUSED));
        self::registerEnchantment(new ForcefieldEnchant($plugin, CustomEnchantIds::FORCEFIELD));
        self::registerEnchantment(new GooeyEnchant($plugin, CustomEnchantIds::GOOEY));
        self::registerEnchantment(new GrapplingEnchant($plugin, CustomEnchantIds::GRAPPLING));
        self::registerEnchantment(new GrowEnchant($plugin, CustomEnchantIds::GROW));
        self::registerEnchantment(new HallucinationEnchant($plugin, CustomEnchantIds::HALLUCINATION));
        self::registerEnchantment(new HarvestEnchant($plugin, CustomEnchantIds::HARVEST));
        self::registerEnchantment(new HeadhunterEnchant($plugin, CustomEnchantIds::HEADHUNTER));
        self::registerEnchantment(new HealingEnchant($plugin, CustomEnchantIds::HEALING));
        self::registerEnchantment(new HeavyEnchant($plugin, CustomEnchantIds::HEAVY));
        self::registerEnchantment(new ImplantsEnchant($plugin, CustomEnchantIds::IMPLANTS));
        self::registerEnchantment(new JackpotEnchant($plugin, CustomEnchantIds::JACKPOT));
        self::registerEnchantment(new JetpackEnchant($plugin, CustomEnchantIds::JETPACK));
        self::registerEnchantment(new LifestealEnchant($plugin, CustomEnchantIds::LIFESTEAL));
        self::registerEnchantment(new LightningEnchant($plugin, CustomEnchantIds::LIGHTNING));
        self::registerEnchantment(new LuckyCharmEnchant($plugin, CustomEnchantIds::LUCKYCHARM));
        self::registerEnchantment(new LumberjackEnchant($plugin, CustomEnchantIds::LUMBERJACK));
        self::registerEnchantment(new MagmaWalkerEnchant($plugin, CustomEnchantIds::MAGMAWALKER));
        self::registerEnchantment(new MeditationEnchant($plugin, CustomEnchantIds::MEDITATION));
        self::registerEnchantment(new MissileEnchant($plugin, CustomEnchantIds::MISSILE));
        self::registerEnchantment(new MolotovEnchant($plugin, CustomEnchantIds::MOLOTOV));
        self::registerEnchantment(new MoltenEnchant($plugin, CustomEnchantIds::MOLTEN));
        self::registerEnchantment(new OverloadEnchant($plugin, CustomEnchantIds::OVERLOAD));
        self::registerEnchantment(new ParachuteEnchant($plugin, CustomEnchantIds::PARACHUTE));
        self::registerEnchantment(new ParalyzeEnchant($plugin, CustomEnchantIds::PARALYZE));
        self::registerEnchantment(new PiercingEnchant($plugin, CustomEnchantIds::PIERCING));
        self::registerEnchantment(new PoisonousCloudEnchant($plugin, CustomEnchantIds::POISONOUSCLOUD));
        self::registerEnchantment(new ProwlEnchant($plugin, CustomEnchantIds::PROWL));
        self::registerEnchantment(new QuickeningEnchant($plugin, CustomEnchantIds::QUICKENING));
        self::registerEnchantment(new RadarEnchant($plugin, CustomEnchantIds::RADAR));
        self::registerEnchantment(new ReviveEnchant($plugin, CustomEnchantIds::REVIVE));
        self::registerEnchantment(new SelfDestructEnchant($plugin, CustomEnchantIds::SELFDESTRUCT));
        self::registerEnchantment(new ShieldedEnchant($plugin, CustomEnchantIds::SHIELDED));
        self::registerEnchantment(new ShrinkEnchant($plugin, CustomEnchantIds::SHRINK));
        self::registerEnchantment(new ShuffleEnchant($plugin, CustomEnchantIds::SHUFFLE));
        self::registerEnchantment(new SmeltingEnchant($plugin, CustomEnchantIds::SMELTING));
        self::registerEnchantment(new SoulboundEnchant($plugin, CustomEnchantIds::SOULBOUND));
        self::registerEnchantment(new SpiderEnchant($plugin, CustomEnchantIds::SPIDER));
        self::registerEnchantment(new StompEnchantment($plugin, CustomEnchantIds::STOMP));
        self::registerEnchantment(new TankEnchant($plugin, CustomEnchantIds::TANK));
        self::registerEnchantment(new TelepathyEnchant($plugin, CustomEnchantIds::TELEPATHY));
        self::registerEnchantment(new VacuumEnchant($plugin, CustomEnchantIds::VACUUM));
        self::registerEnchantment(new VampireEnchant($plugin, CustomEnchantIds::VAMPIRE));
        self::registerEnchantment(new VolleyEnchant($plugin, CustomEnchantIds::VOLLEY));
    }

    public static function getPlugin(): PiggyCustomEnchants
    {
        return self::$plugin;
    }

    public static function registerEnchantment(CustomEnchant $enchant): void
    {
        EnchantmentIdMap::getInstance()->register($enchant->getId(), $enchant);
        self::$enchants[$enchant->getId()] = $enchant;
        StringToEnchantmentParser::getInstance()->register($enchant->name, fn() => $enchant);
        if ($enchant->name !== $enchant->getDisplayName()) StringToEnchantmentParser::getInstance()->register($enchant->getDisplayName(), fn() => $enchant);

        self::$plugin->getLogger()->debug("Custom Enchantment '" . $enchant->getDisplayName() . "' registered with id " . $enchant->getId());
    }

    public static function unregisterEnchantment(int|CustomEnchant $id): void
    {
        $id = $id instanceof CustomEnchant ? $id->getId() : $id;
        $enchant = self::$enchants[$id];

        $property = new ReflectionProperty(StringToTParser::class, "callbackMap");
        $property->setAccessible(true);
        $value = $property->getValue(StringToEnchantmentParser::getInstance());
        unset($value[strtolower(str_replace([" ", "minecraft:"], ["_", ""], trim($enchant->name)))]);
        if ($enchant->name !== $enchant->getDisplayName()) unset($value[strtolower(str_replace([" ", "minecraft:"], ["_", ""], trim($enchant->getDisplayName())))]);
        $property->setValue(StringToEnchantmentParser::getInstance(), $value);

        self::$plugin->getLogger()->debug("Custom Enchantment '" . $enchant->getDisplayName() . "' unregistered with id " . $enchant->getId());
        unset(self::$enchants[$id]);

        $property = new ReflectionProperty(EnchantmentIdMap::class, "enchToId");
        $property->setAccessible(true);
        $value = $property->getValue(EnchantmentIdMap::getInstance());
        unset($value[spl_object_id(EnchantmentIdMap::getInstance()->fromId($id))]);
        $property->setValue(EnchantmentIdMap::getInstance(), $value);

        $property = new ReflectionProperty(EnchantmentIdMap::class, "idToEnch");
        $property->setAccessible(true);
        $value = $property->getValue(EnchantmentIdMap::getInstance());
        unset($value[$id]);
        $property->setValue(EnchantmentIdMap::getInstance(), $value);
    }

    /**
     * @return CustomEnchant[]
     */
    public static function getEnchantments(): array
    {
        return self::$enchants;
    }

    public static function getEnchantment(int $id): ?CustomEnchant
    {
        return self::$enchants[$id] ?? null;
    }

    public static function getEnchantmentByName(string $name): ?CustomEnchant
    {
        return ($enchant = StringToEnchantmentParser::getInstance()->parse($name)) instanceof CustomEnchant ? $enchant : null;
    }
}


================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/EventListener.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\tools\DrillerEnchant;
use DaPigGuy\PiggyCustomEnchants\entities\BombardmentTNT;
use DaPigGuy\PiggyCustomEnchants\entities\PiggyTNT;
use DaPigGuy\PiggyCustomEnchants\utils\ProjectileTracker;
use DaPigGuy\PiggyCustomEnchants\utils\Utils;
use pocketmine\block\BlockLegacyIds;
use pocketmine\event\block\BlockBreakEvent;
use pocketmine\event\entity\EntityBlockChangeEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityEffectAddEvent;
use pocketmine\event\entity\EntityShootBowEvent;
use pocketmine\event\entity\ProjectileHitBlockEvent;
use pocketmine\event\entity\ProjectileLaunchEvent;
use pocketmine\event\inventory\InventoryTransactionEvent;
use pocketmine\event\Listener;
use pocketmine\event\player\PlayerDeathEvent;
use pocketmine\event\player\PlayerInteractEvent;
use pocketmine\event\player\PlayerItemHeldEvent;
use pocketmine\event\player\PlayerJoinEvent;
use pocketmine\event\player\PlayerMoveEvent;
use pocketmine\event\player\PlayerQuitEvent;
use pocketmine\event\player\PlayerToggleSneakEvent;
use pocketmine\event\server\DataPacketReceiveEvent;
use pocketmine\event\server\DataPacketSendEvent;
use pocketmine\inventory\ArmorInventory;
use pocketmine\inventory\CallbackInventoryListener;
use pocketmine\inventory\Inventory;
use pocketmine\inventory\PlayerInventory;
use pocketmine\inventory\transaction\action\SlotChangeAction;
use pocketmine\item\enchantment\EnchantmentInstance;
use pocketmine\item\Item;
use pocketmine\item\ItemIds;
use pocketmine\item\VanillaItems;
use pocketmine\network\mcpe\protocol\InventoryContentPacket;
use pocketmine\network\mcpe\protocol\InventorySlotPacket;
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
use pocketmine\network\mcpe\protocol\PlayerActionPacket;
use pocketmine\network\mcpe\protocol\PlayerAuthInputPacket;
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
use pocketmine\network\mcpe\protocol\types\PlayerAction;
use pocketmine\network\mcpe\protocol\types\PlayerBlockActionWithBlockInfo;
use pocketmine\player\Player;

class EventListener implements Listener
{
    public function __construct(private PiggyCustomEnchants $plugin)
    {
    }

    /**
     * @priority HIGHEST
     */
    public function onBreak(BlockBreakEvent $event): void
    {
        $player = $event->getPlayer();
        ReactiveEnchantment::attemptReaction($player, $event);
    }

    public function onDataPacketReceive(DataPacketReceiveEvent $event): void
    {
        $packet = $event->getPacket();
        if ($packet instanceof InventoryTransactionPacket) {
            $transaction = $packet->trData;
            foreach ($transaction->getActions() as $action) {
                $action->oldItem = new ItemStackWrapper($action->oldItem->getStackId(), Utils::filterDisplayedEnchants($action->oldItem->getItemStack()));
                $action->newItem = new ItemStackWrapper($action->newItem->getStackId(), Utils::filterDisplayedEnchants($action->newItem->getItemStack()));
            }
        }
        if ($packet instanceof PlayerActionPacket) {
            if ($packet->action === PlayerAction::START_BREAK || $packet->action === PlayerAction::CREATIVE_PLAYER_DESTROY_BLOCK) {
                DrillerEnchant::$lastBreakFace[$event->getOrigin()->getPlayer()->getName()] = $packet->face;
            }
        }
        if ($packet instanceof PlayerAuthInputPacket) {
            $blockActions = $packet->getBlockActions();
            if ($blockActions !== null) {
                foreach ($blockActions as $blockAction) {
                    if ($blockAction instanceof PlayerBlockActionWithBlockInfo) {
                        DrillerEnchant::$lastBreakFace[$event->getOrigin()->getPlayer()->getName()] = $blockAction->getFace();
                    }
                }
            }
        }
        if ($packet instanceof MobEquipmentPacket) Utils::filterDisplayedEnchants($packet->item->getItemStack());
    }

    public function onDataPacketSend(DataPacketSendEvent $event): void
    {
        $packets = $event->getPackets();
        foreach ($packets as $packet) {
            if ($packet instanceof InventorySlotPacket) {
                $packet->item = new ItemStackWrapper($packet->item->getStackId(), Utils::displayEnchants($packet->item->getItemStack()));
            }
            if ($packet instanceof InventoryContentPacket) {
                foreach ($packet->items as $i => $item) {
                    $packet->items[$i] = new ItemStackWrapper($item->getStackId(), Utils::displayEnchants($item->getItemStack()));
                }
            }
        }
    }

    public function onBlockChange(EntityBlockChangeEvent $event): void
    {
        $entity = $event->getEntity();
        if ($entity instanceof BombardmentTNT) {
            for ($i = 0; $i < 3 + $entity->getEnchantmentLevel(); $i++) {
                $tnt = new PiggyTNT($entity->getLocation(), null, $this->plugin->getConfig()->getNested("world-damage.missile", false));
                $tnt->setFuse(0);
                $tnt->setOwningEntity($entity->getOwningEntity());
                $tnt->spawnToAll();
            }
            $event->cancel();
        }
    }

    /**
     * @priority HIGHEST
     */
    public function onDamage(EntityDamageEvent $event): void
    {
        $entity = $event->getEntity();
        if ($entity instanceof Player) {
            if ($event->getCause() === EntityDamageEvent::CAUSE_FALL && !Utils::shouldTakeFallDamage($entity)) {
                if ($entity->getArmorInventory()->getBoots()->getEnchantment(CustomEnchantManager::getEnchantment(CustomEnchantIds::SPRINGS)) === null) Utils::setShouldTakeFallDamage($entity, true);
                $event->cancel();
                return;
            }
            ReactiveEnchantment::attemptReaction($entity, $event);
        }
        if ($event instanceof EntityDamageByEntityEvent) {
            $attacker = $event->getDamager();
            if ($attacker instanceof Player) ReactiveEnchantment::attemptReaction($attacker, $event);
        }
    }

    /**
     * @priority HIGHEST
     */
    public function onEffectAdd(EntityEffectAddEvent $event): void
    {
        $entity = $event->getEntity();
        if ($entity instanceof Player) ReactiveEnchantment::attemptReaction($entity, $event);
    }

    /**
     * @priority HIGHEST
     */
    public function onShootBow(EntityShootBowEvent $event): void
    {
        $entity = $event->getEntity();
        if ($entity instanceof Player) ReactiveEnchantment::attemptReaction($entity, $event);
    }

    public function onDeath(PlayerDeathEvent $event): void
    {
        ReactiveEnchantment::attemptReaction($event->getPlayer(), $event);
    }

    /**
     * @priority HIGHEST
     */
    public function onInteract(PlayerInteractEvent $event): void
    {
        ReactiveEnchantment::attemptReaction($event->getPlayer(), $event);
    }

    /**
     * @priority HIGHEST
     */
    public function onItemHold(PlayerItemHeldEvent $event): void
    {
        $player = $event->getPlayer();
        $inventory = $player->getInventory();
        $oldItem = $inventory->getItemInHand();
        $newItem = $event->getItem();
        foreach ($oldItem->getEnchantments() as $enchantmentInstance) ToggleableEnchantment::attemptToggle($player, $oldItem, $enchantmentInstance, $inventory, $inventory->getHeldItemIndex(), false);
        foreach ($newItem->getEnchantments() as $enchantmentInstance) ToggleableEnchantment::attemptToggle($player, $newItem, $enchantmentInstance, $inventory, $inventory->getHeldItemIndex());
    }

    public function onJoin(PlayerJoinEvent $event): void
    {
        $player = $event->getPlayer();
        foreach ($player->getInventory()->getContents() as $slot => $content) {
            foreach ($content->getEnchantments() as $enchantmentInstance) {
                ToggleableEnchantment::attemptToggle($player, $content, $enchantmentInstance, $player->getInventory(), $slot);
            }
        }
        foreach ($player->getArmorInventory()->getContents() as $slot => $content) {
            foreach ($content->getEnchantments() as $enchantmentInstance) {
                ToggleableEnchantment::attemptToggle($player, $content, $enchantmentInstance, $player->getArmorInventory(), $slot);
            }
        }

        $onSlot = function (Inventory $inventory, int $slot, Item $oldItem): void {
            if ($inventory instanceof PlayerInventory || $inventory instanceof ArmorInventory) {
                $holder = $inventory->getHolder();
                if ($holder instanceof Player) {
                    if (!$oldItem->equals(($newItem = $inventory->getItem($slot)), !$inventory instanceof ArmorInventory)) {
                        if ($newItem->getId() === ItemIds::AIR || $inventory instanceof ArmorInventory) foreach ($oldItem->getEnchantments() as $oldEnchantment) ToggleableEnchantment::attemptToggle($holder, $oldItem, $oldEnchantment, $inventory, $slot, false);
                        if ($oldItem->getId() === ItemIds::AIR || $inventory instanceof ArmorInventory) foreach ($newItem->getEnchantments() as $newEnchantment) ToggleableEnchantment::attemptToggle($holder, $newItem, $newEnchantment, $inventory, $slot);
                    }
                }
            }
        };
        /**
         * @param Item[] $oldContents
         */
        $onContent = function (Inventory $inventory, array $oldContents) use ($onSlot): void {
            foreach ($oldContents as $slot => $oldItem) {
                if (!($oldItem ?? VanillaItems::AIR())->equals($inventory->getItem($slot), !$inventory instanceof ArmorInventory)) {
                    $onSlot($inventory, $slot, $oldItem);
                }
            }
        };
        $player->getInventory()->getListeners()->add(new CallbackInventoryListener($onSlot, $onContent));
        $player->getArmorInventory()->getListeners()->add(new CallbackInventoryListener($onSlot, $onContent));
    }

    /**
     * @priority HIGHEST
     */
    public function onMove(PlayerMoveEvent $event): void
    {
        $player = $event->getPlayer();
        if (!Utils::shouldTakeFallDamage($player)) {
            if ($player->getWorld()->getBlock($player->getPosition()->floor()->subtract(0, 1, 0))->getId() !== BlockLegacyIds::AIR && Utils::getNoFallDamageDuration($player) <= 0) {
                Utils::setShouldTakeFallDamage($player, true);
            } else {
                Utils::increaseNoFallDamageDuration($player);
            }
        }
        if ($event->getFrom()->floor()->equals($event->getTo()->floor())) return;
        ReactiveEnchantment::attemptReaction($player, $event);
    }

    /**
     * @priority MONITOR
     */
    public function onQuit(PlayerQuitEvent $event): void
    {
        $player = $event->getPlayer();
        if (!$player->isClosed()) {
            foreach ($player->getInventory()->getContents() as $slot => $content) {
                foreach ($content->getEnchantments() as $enchantmentInstance) {
                    ToggleableEnchantment::attemptToggle($player, $content, $enchantmentInstance, $player->getInventory(), $slot, false);
                }
            }
            foreach ($player->getArmorInventory()->getContents() as $slot => $content) {
                foreach ($content->getEnchantments() as $enchantmentInstance) {
                    ToggleableEnchantment::attemptToggle($player, $content, $enchantmentInstance, $player->getArmorInventory(), $slot, false);
                }
            }
        }
    }

    /**
     * @priority HIGHEST
     */
    public function onSneak(PlayerToggleSneakEvent $event): void
    {
        ReactiveEnchantment::attemptReaction($event->getPlayer(), $event);
    }

    /**
     * @priority HIGHEST
     */
    public function onProjectileHitBlock(ProjectileHitBlockEvent $event): void
    {
        $shooter = $event->getEntity()->getOwningEntity();
        if ($shooter instanceof Player) ReactiveEnchantment::attemptReaction($shooter, $event);
    }

    /**
     * @priority HIGHEST
     */
    public function onProjectileLaunch(ProjectileLaunchEvent $event): void
    {
        $projectile = $event->getEntity();
        $shooter = $projectile->getOwningEntity();
        if ($shooter instanceof Player) ProjectileTracker::addProjectile($projectile, $shooter->getInventory()->getItemInHand());
    }

    /**
     * @priority HIGHEST
     */
    public function onTransaction(InventoryTransactionEvent $event): void
    {
        if ($this->plugin->getConfig()->getNested("enchants.books", true) === false) return;
        $transaction = $event->getTransaction();
        $actions = array_values($transaction->getActions());
        if (count($actions) === 2) {
            foreach ($actions as $i => $action) {
                if ($action instanceof SlotChangeAction && ($otherAction = $actions[($i + 1) % 2]) instanceof SlotChangeAction && ($itemClickedWith = $action->getTargetItem())->getId() === ItemIds::ENCHANTED_BOOK && ($itemClicked = $action->getSourceItem())->getId() !== ItemIds::AIR && ($itemClicked->getId() !== ItemIds::ENCHANTED_BOOK || count($itemClicked->getEnchantments()) >= count($itemClickedWith->getEnchantments()))) {
                    if (count($itemClickedWith->getEnchantments()) < 1) return;
                    $enchantmentSuccessful = false;
                    foreach ($itemClickedWith->getEnchantments() as $enchantment) {
                        $enchantmentType = $enchantment->getType();
                        $newLevel = $enchantment->getLevel();
                        $willChange = false;
                        if (($existingEnchant = $itemClicked->getEnchantment($enchantmentType)) !== null) {
                            if ($existingEnchant->getLevel() > $newLevel) continue;
                            if ($existingEnchant->getLevel() === $newLevel) {
                                $newLevel++;
                                $willChange = true;
                            }
                        } else {
                            $willChange = true;
                        }
                        if (
                            ($enchantmentType instanceof CustomEnchant &&
                                (!Utils::itemMatchesItemType($itemClicked, $enchantmentType->getItemType()) || !Utils::checkEnchantIncompatibilities($itemClicked, $enchantmentType))
                            ) ||
                            $itemClicked->getCount() !== 1 ||
                            $newLevel > $enchantmentType->getMaxLevel() ||
                            ($itemClicked->getId() === ItemIds::ENCHANTED_BOOK && count($itemClicked->getEnchantments()) === 0) ||
                            $itemClicked->getId() === ItemIds::BOOK
                        ) continue;
                        $itemClicked->addEnchantment(new EnchantmentInstance($enchantmentType, $newLevel));
                        if ($willChange) $enchantmentSuccessful = true;
                    }
                    if ($enchantmentSuccessful) {
                        $event->cancel();
                        $action->getInventory()->setItem($action->getSlot(), $itemClicked);
                        $otherAction->getInventory()->setItem($otherAction->getSlot(), VanillaItems::AIR());
                    }
                }
            }
        }
    }
}


================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/PiggyCustomEnchants.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants;

use CortexPE\Commando\BaseCommand;
use CortexPE\Commando\PacketHooker;
use DaPigGuy\libPiggyUpdateChecker\libPiggyUpdateChecker;
use DaPigGuy\PiggyCustomEnchants\blocks\PiggyObsidian;
use DaPigGuy\PiggyCustomEnchants\commands\CustomEnchantsCommand;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use DaPigGuy\PiggyCustomEnchants\entities\BombardmentTNT;
use DaPigGuy\PiggyCustomEnchants\entities\HomingArrow;
use DaPigGuy\PiggyCustomEnchants\entities\PiggyFireball;
use DaPigGuy\PiggyCustomEnchants\entities\PiggyLightning;
use DaPigGuy\PiggyCustomEnchants\entities\PiggyTNT;
use DaPigGuy\PiggyCustomEnchants\entities\PiggyWitherSkull;
use DaPigGuy\PiggyCustomEnchants\entities\PigProjectile;
use DaPigGuy\PiggyCustomEnchants\tasks\CheckDisabledEnchantsTask;
use DaPigGuy\PiggyCustomEnchants\tasks\TickEnchantmentsTask;
use jojoe77777\FormAPI\Form;
use pocketmine\block\BlockFactory;
use pocketmine\color\Color;
use pocketmine\data\bedrock\EffectIdMap;
use pocketmine\entity\effect\Effect;
use pocketmine\entity\EntityDataHelper;
use pocketmine\entity\EntityFactory;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\plugin\PluginBase;
use pocketmine\utils\Config;
use pocketmine\world\World;

class PiggyCustomEnchants extends PluginBase
{
    public static Effect $SLOW_FALL;

    /** @var mixed[] */
    private array $enchantmentData;

    public function onEnable(): void
    {
        foreach (
            [
                "Commando" => BaseCommand::class,
                "libformapi" => Form::class,
                "libPiggyUpdateChecker" => libPiggyUpdateChecker::class
            ] as $virion => $class
        ) {
            if (!class_exists($class)) {
                $this->getLogger()->error($virion . " virion not found. Download PiggyCustomEnchants at https://poggit.pmmp.io/p/PiggyCustomEnchants for a pre-compiled phar.");
                $this->getServer()->getPluginManager()->disablePlugin($this);
                return;
            }
        }

        foreach (["rarities", "max_levels", "display_names", "descriptions", "extra_data", "cooldowns", "chances"] as $file) {
            $this->saveResource($file . ".json");
            foreach ((new Config($this->getDataFolder() . $file . ".json"))->getAll() as $enchant => $data) {
                $this->enchantmentData[$enchant][$file] = $data;
            }
        }
        $this->saveDefaultConfig();

        CustomEnchantManager::init($this);

        BlockFactory::getInstance()->register(new PiggyObsidian(), true);

        //TODO: Use real effect
        self::$SLOW_FALL = new Effect("%potion.slowFalling", new Color(206, 255, 255));
        EffectIdMap::getInstance()->register(27, self::$SLOW_FALL);

        $entityFactory = EntityFactory::getInstance();
        $entityFactory->register(BombardmentTNT::class, function (World $world, CompoundTag $nbt): BombardmentTNT {
            return new BombardmentTNT(EntityDataHelper::parseLocation($nbt, $world), $nbt, $nbt->getInt("Level", 1));
        }, ["BombardmentTNT"]);
        $entityFactory->register(HomingArrow::class, function (World $world, CompoundTag $nbt): HomingArrow {
            return new HomingArrow(EntityDataHelper::parseLocation($nbt, $world), null, false, $nbt, $nbt->getInt("Level", 1));
        }, ["HomingArrow"]);
        $entityFactory->register(PigProjectile::class, function (World $world, CompoundTag $nbt): PigProjectile {
            return new PigProjectile(EntityDataHelper::parseLocation($nbt, $world), null, $nbt);
        }, ["PigProjectile"]);
        $entityFactory->register(PiggyFireball::class, function (World $world, CompoundTag $nbt): PiggyFireball {
            return new PiggyFireball(EntityDataHelper::parseLocation($nbt, $world), null, $nbt);
        }, ["PiggyFireball"]);
        $entityFactory->register(PiggyLightning::class, function (World $world, CompoundTag $nbt): PiggyLightning {
            return new PiggyLightning(EntityDataHelper::parseLocation($nbt, $world), $nbt);
        }, ["PiggyLightning"]);
        $entityFactory->register(PiggyTNT::class, function (World $world, CompoundTag $nbt): PiggyTNT {
            return new PiggyTNT(EntityDataHelper::parseLocation($nbt, $world), $nbt);
        }, ["PiggyTNT"]);
        $entityFactory->register(PiggyWitherSkull::class, function (World $world, CompoundTag $nbt): PiggyWitherSkull {
            return new PiggyWitherSkull(EntityDataHelper::parseLocation($nbt, $world), null, $nbt);
        }, ["PiggyWitherSkull"]);

        foreach ($this->getConfig()->get("disabled-enchants", []) as $enchant) {
            $e = CustomEnchantManager::getEnchantmentByName($enchant);
            if ($e instanceof CustomEnchant) CustomEnchantManager::unregisterEnchantment($e->getId());
        }

        if (!PacketHooker::isRegistered()) PacketHooker::register($this);
        $this->getServer()->getCommandMap()->register("piggycustomenchants", new CustomEnchantsCommand($this, "customenchants", "Manage Custom Enchants", ["ce", "customenchant"]));

        $this->getServer()->getPluginManager()->registerEvents(new EventListener($this), $this);
        $this->getScheduler()->scheduleRepeatingTask(new TickEnchantmentsTask($this), 1);

        libPiggyUpdateChecker::init($this);
        if ($this->getConfig()->get("remote-disable", true) === true) $this->getServer()->getAsyncPool()->submitTask(new CheckDisabledEnchantsTask());
    }

    public function onDisable(): void
    {
        foreach ($this->getServer()->getOnlinePlayers() as $player) {
            foreach ($player->getInventory()->getContents() as $slot => $content) {
                foreach ($content->getEnchantments() as $enchantmentInstance) {
                    ToggleableEnchantment::attemptToggle($player, $content, $enchantmentInstance, $player->getInventory(), $slot, false);
                }
            }
            foreach ($player->getArmorInventory()->getContents() as $slot => $content) {
                foreach ($content->getEnchantments() as $enchantmentInstance) {
                    ToggleableEnchantment::attemptToggle($player, $content, $enchantmentInstance, $player->getArmorInventory(), $slot, false);
                }
            }
        }
    }

    /**
     * @internal
     */
    public function getEnchantmentData(string $enchant, string $data, int|string|array $default = ""): mixed
    {
        if (!isset($this->enchantmentData[str_replace(" ", "", strtolower($enchant))][$data])) $this->setEnchantmentData($enchant, $data, $default);
        return $this->enchantmentData[str_replace(" ", "", strtolower($enchant))][$data];
    }

    public function setEnchantmentData(string $enchant, string $data, int|string|array $value): void
    {
        $this->enchantmentData[str_replace(" ", "", strtolower($enchant))][$data] = $value;
        $config = new Config($this->getDataFolder() . $data . ".json");
        $config->set(str_replace(" ", "", strtolower($enchant)), $value);
        $config->save();
    }

    /**
     * @internal
     */
    public function areFormsEnabled(): bool
    {
        return $this->getConfig()->getNested("forms.enabled", true);
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/blocks/PiggyObsidian.php
================================================
<?php

namespace DaPigGuy\PiggyCustomEnchants\blocks;

use pocketmine\block\Block;
use pocketmine\block\BlockBreakInfo;
use pocketmine\block\BlockIdentifier;
use pocketmine\block\BlockLegacyIds;
use pocketmine\block\VanillaBlocks;
use pocketmine\item\Item;
use pocketmine\player\Player;

class PiggyObsidian extends Block
{
    private int $age = 0;

    public function __construct()
    {
        parent::__construct(new BlockIdentifier(BlockLegacyIds::OBSIDIAN, 15), "Magmawalker Obsidian", BlockBreakInfo::instant());
    }

    public function onScheduledUpdate(): void
    {
        if (mt_rand(0, 3) === 0 || $this->countNeighbors() < 4) {
            $this->slightlyMelt(true);
        } else {
            $this->getPosition()->getWorld()->scheduleDelayedBlockUpdate($this->getPosition(), mt_rand(20, 40));
        }
    }

    public function onBreak(Item $item, Player $player = null): bool
    {
        $this->getPosition()->getWorld()->setBlock($this->getPosition(), VanillaBlocks::LAVA());
        return true;
    }

    public function getDrops(Item $item): array
    {
        return [];
    }

    public function countNeighbors(): int
    {
        $i = 0;
        foreach ($this->getAllSides() as $block) {
            if ($block instanceof PiggyObsidian) {
                $i++;
                if ($i >= 4) return $i;
            }
        }
        return $i;
    }

    public function slightlyMelt(bool $meltNeighbors): void
    {
        if ($this->age < 3) {
            $this->age++;
            $this->getPosition()->getWorld()->scheduleDelayedBlockUpdate($this->getPosition(), mt_rand(20, 40));
        } else {
            $this->getPosition()->getWorld()->useBreakOn($this->getPosition());
            if ($meltNeighbors) {
                foreach ($this->getAllSides() as $block) {
                    if ($block instanceof PiggyObsidian) {
                        $block->slightlyMelt(false);
                    }
                }
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/commands/CustomEnchantsCommand.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\commands;

use CortexPE\Commando\BaseCommand;
use CortexPE\Commando\BaseSubCommand;
use DaPigGuy\PiggyCustomEnchants\commands\subcommands\AboutSubCommand;
use DaPigGuy\PiggyCustomEnchants\commands\subcommands\EnchantSubCommand;
use DaPigGuy\PiggyCustomEnchants\commands\subcommands\InfoSubCommand;
use DaPigGuy\PiggyCustomEnchants\commands\subcommands\ListSubCommand;
use DaPigGuy\PiggyCustomEnchants\commands\subcommands\NBTSubCommand;
use DaPigGuy\PiggyCustomEnchants\commands\subcommands\RemoveSubCommand;
use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use jojoe77777\FormAPI\SimpleForm;
use pocketmine\command\CommandSender;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class CustomEnchantsCommand extends BaseCommand
{
    /** @var PiggyCustomEnchants */
    protected $plugin;

    public function onRun(CommandSender $sender, string $aliasUsed, array $args): void
    {
        $subcommands = array_values(array_map(function (BaseSubCommand $subCommand): string {
            return $subCommand->getName();
        }, $this->getSubCommands()));
        if ($sender instanceof Player && $this->plugin->areFormsEnabled()) {
            $form = new SimpleForm(function (Player $player, ?int $data) use ($subcommands): void {
                if ($data !== null && isset($subcommands[$data])) {
                    $this->plugin->getServer()->dispatchCommand($player, "ce " . $subcommands[$data]);
                }
            });
            $form->setTitle(TextFormat::GREEN . "PiggyCustomEnchants Menu");
            foreach ($subcommands as $subcommand) $form->addButton(ucfirst($subcommand));
            $sender->sendForm($form);
            return;
        }
        $sender->sendMessage("Usage: /ce <" . implode("|", $subcommands) . ">");
    }

    public function prepare(): void
    {
        $this->registerSubCommand(new AboutSubCommand($this->plugin, "about", "Displays basic information about the plugin"));
        $this->registerSubCommand(new EnchantSubCommand($this->plugin, "enchant", "Apply an enchantment on an item"));
        $this->registerSubCommand(new InfoSubCommand($this->plugin, "info", "Get info on a custom enchant"));
        $this->registerSubCommand(new ListSubCommand($this->plugin, "list", "Lists all registered custom enchants"));
        $this->registerSubCommand(new NBTSubCommand($this->plugin, "nbt", "Displays NBT tags of currently held item"));
        $this->registerSubCommand(new RemoveSubCommand($this->plugin, "remove", "Remove an enchantment from an item"));
    }
}


================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/AboutSubCommand.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\commands\subcommands;

use CortexPE\Commando\BaseSubCommand;
use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use jojoe77777\FormAPI\SimpleForm;
use pocketmine\command\CommandSender;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class AboutSubCommand extends BaseSubCommand
{
    /** @var PiggyCustomEnchants */
    protected $plugin;

    public function onRun(CommandSender $sender, string $aliasUsed, array $args): void
    {
        $message = TextFormat::GREEN . "PiggyCustomEnchants version " . TextFormat::GOLD . $this->plugin->getDescription()->getVersion() . TextFormat::EOL .
            TextFormat::GREEN . "PiggyCustomEnchants is a versatile custom enchantments plugin developed by DaPigGuy (MCPEPIG) and Aericio." . TextFormat::EOL .
            "More information about our plugin can be found at " . TextFormat::GOLD . "https://piggydocs.aericio.net/" . TextFormat::GREEN . "." . TextFormat::EOL .
            TextFormat::GRAY . "Copyright 2017 DaPigGuy; Licensed under the Apache License.";
        if ($sender instanceof Player && $this->plugin->areFormsEnabled()) {
            $form = new SimpleForm(function (Player $player, ?int $data): void {
                if ($data !== null) $this->plugin->getServer()->dispatchCommand($player, "ce");
            });
            $form->setTitle(TextFormat::GREEN . "About PiggyCustomEnchants");
            $form->setContent($message);
            $form->addButton("Back");
            $sender->sendForm($form);
            return;
        }
        $sender->sendMessage($message);
    }

    public function prepare(): void
    {
        $this->setPermission("piggycustomenchants.command.ce.about");
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/EnchantSubCommand.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\commands\subcommands;

use CortexPE\Commando\args\IntegerArgument;
use CortexPE\Commando\args\RawStringArgument;
use CortexPE\Commando\BaseSubCommand;
use CortexPE\Commando\exception\ArgumentOrderException;
use DaPigGuy\PiggyCustomEnchants\CustomEnchantManager;
use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use DaPigGuy\PiggyCustomEnchants\utils\Utils;
use jojoe77777\FormAPI\CustomForm;
use pocketmine\command\CommandSender;
use pocketmine\item\enchantment\EnchantmentInstance;
use pocketmine\item\ItemIds;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;
use Ramsey\Uuid\Uuid;

class EnchantSubCommand extends BaseSubCommand
{
    /** @var PiggyCustomEnchants */
    protected $plugin;

    public function onRun(CommandSender $sender, string $aliasUsed, array $args): void
    {
        if ($sender instanceof Player && $this->plugin->areFormsEnabled() && !isset($args["enchantment"])) {
            $this->onRunForm($sender, $aliasUsed, $args);
            return;
        }
        if ((!$sender instanceof Player && empty($args["player"])) || !isset($args["enchantment"])) {
            $sender->sendMessage("Usage: /ce enchant <enchantment> <level> <player>");
            return;
        }
        $args["level"] = empty($args["level"]) ? 1 : $args["level"];
        if (!is_int($args["level"])) {
            $sender->sendMessage(TextFormat::RED . "Enchantment level must be an integer");
            return;
        }
        $target = empty($args["player"]) ? $sender : $this->plugin->getServer()->getPlayerByPrefix($args["player"]);
        if (!$target instanceof Player) {
            $sender->sendMessage(TextFormat::RED . "Invalid player.");
            return;
        }
        $enchant = CustomEnchantManager::getEnchantmentByName($args["enchantment"]);
        if ($enchant === null) {
            $sender->sendMessage(TextFormat::RED . "Invalid enchantment.");
            return;
        }
        $item = $target->getInventory()->getItemInHand();
        if (!$sender->hasPermission("piggycustomenchants.overridecheck")) {
            if (!Utils::itemMatchesItemType($item, $enchant->getItemType())) {
                $sender->sendMessage(TextFormat::RED . "The item is not compatible with this enchant.");
                return;
            }
            if ($args["level"] > $enchant->getMaxLevel()) {
                $sender->sendMessage(TextFormat::RED . "The max level is " . $enchant->getMaxLevel() . ".");
                return;
            }
            if ($item->getCount() > 1) {
                $sender->sendMessage(TextFormat::RED . "You can only enchant one item at a time.");
                return;
            }
            if (!Utils::checkEnchantIncompatibilities($item, $enchant)) {
                $sender->sendMessage(TextFormat::RED . "This enchant is not compatible with another enchant.");
                return;
            }
        }
        if ($item->getId() === ItemIds::ENCHANTED_BOOK || $item->getId() === ItemIds::BOOK) {
            $item->getNamedTag()->setString("PiggyCEBookUUID", Uuid::uuid4()->toString());
        }
        $item->addEnchantment(new EnchantmentInstance($enchant, $args["level"]));
        $sender->sendMessage(TextFormat::GREEN . "Item successfully enchanted.");
        $target->getInventory()->setItemInHand($item);
    }

    public function onRunForm(CommandSender $sender, string $aliasUsed, array $args): void
    {
        if ($sender instanceof Player) {
            $form = new CustomForm(function (Player $player, ?array $data): void {
                if ($data !== null) {
                    $enchant = is_numeric($data[0]) ? CustomEnchantManager::getEnchantment((int)$data[0]) : CustomEnchantManager::getEnchantmentByName($data[0]);
                    if ($enchant == null) {
                        Utils::errorForm($player, TextFormat::RED . "Invalid enchantment.");
                        return;
                    }
                    $target = $this->plugin->getServer()->getPlayerByPrefix($data[2]);
                    if (!$target instanceof Player) {
                        Utils::errorForm($player, TextFormat::RED . "Invalid player.");
                        return;
                    }
                    $item = $target->getInventory()->getItemInHand();
                    if (!$player->hasPermission("piggycustomenchants.overridecheck")) {
                        if (!Utils::itemMatchesItemType($item, $enchant->getItemType())) {
                            Utils::errorForm($player, TextFormat::RED . "The item is not compatible with this enchant.");
                            return;
                        }
                        if ($data[1] > $enchant->getMaxLevel()) {
                            Utils::errorForm($player, TextFormat::RED . "The max level is " . $enchant->getMaxLevel() . ".");
                            return;
                        }
                        if (($enchantmentInstance = $item->getEnchantment($enchant)) !== null && $enchantmentInstance->getLevel() > $data[1]) {
                            Utils::errorForm($player, TextFormat::RED . "The enchant has already been applied with a higher level on the item.");
                            return;
                        }
                        if ($item->getCount() > 1) {
                            Utils::errorForm($player, TextFormat::RED . "You can only enchant one item at a time.");
                            return;
                        }
                        if (!Utils::checkEnchantIncompatibilities($item, $enchant)) {
                            Utils::errorForm($player, TextFormat::RED . "This enchant is not compatible with another enchant.");
                            return;
                        }
                    }
                    if ($item->getId() === ItemIds::ENCHANTED_BOOK || $item->getId() === ItemIds::BOOK) {
                        $item->getNamedTag()->setString("PiggyCEBookUUID", Uuid::uuid4()->toString());
                    }
                    $item->addEnchantment(new EnchantmentInstance($enchant, (int)$data[1]));
                    $player->sendMessage(TextFormat::GREEN . "Item successfully enchanted.");
                    $target->getInventory()->setItemInHand($item);
                }
            });
            $form->setTitle(TextFormat::GREEN . "Apply Custom Enchantment");
            $form->addInput("Enchantment");
            $form->addInput("Level", "", "1");
            $form->addInput("Player", "", $sender->getName());
            $sender->sendForm($form);
        }
    }

    /**
     * @throws ArgumentOrderException
     */
    public function prepare(): void
    {
        $this->setPermission("piggycustomenchants.command.ce.enchant");
        $this->registerArgument(0, new RawStringArgument("enchantment", true));
        $this->registerArgument(1, new IntegerArgument("level", true));
        $this->registerArgument(2, new RawStringArgument("player", true));
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/InfoSubCommand.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\commands\subcommands;

use CortexPE\Commando\args\RawStringArgument;
use CortexPE\Commando\BaseSubCommand;
use CortexPE\Commando\exception\ArgumentOrderException;
use DaPigGuy\PiggyCustomEnchants\CustomEnchantManager;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use DaPigGuy\PiggyCustomEnchants\utils\Utils;
use jojoe77777\FormAPI\CustomForm;
use jojoe77777\FormAPI\SimpleForm;
use pocketmine\command\CommandSender;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class InfoSubCommand extends BaseSubCommand
{
    /** @var PiggyCustomEnchants */
    protected $plugin;

    public function onRun(CommandSender $sender, string $aliasUsed, array $args): void
    {
        if ($sender instanceof Player && $this->plugin->areFormsEnabled()) {
            if (isset($args["enchantment"])) {
                $enchantment = CustomEnchantManager::getEnchantmentByName($args["enchantment"]);
                if ($enchantment === null) {
                    Utils::errorForm($sender, TextFormat::RED . "Invalid enchantment.");
                    return;
                }
                $this->showInfo($sender, $enchantment);
                return;
            }
            $form = new CustomForm(function (Player $player, ?array $data) {
                if ($data !== null) {
                    $enchantment = CustomEnchantManager::getEnchantmentByName($data[0]);
                    if ($enchantment === null) {
                        Utils::errorForm($player, TextFormat::RED . "Invalid enchantment.");
                        return;
                    }
                    $this->showInfo($player, $enchantment);
                }
            });
            $form->setTitle(TextFormat::GREEN . "Custom Enchant Info");
            $form->addInput("Enchantment");
            $sender->sendForm($form);
            return;
        }
        if (!isset($args["enchantment"])) {
            $sender->sendMessage("/ce info <enchantment>");
            return;
        }
        $enchantment = CustomEnchantManager::getEnchantmentByName($args["enchantment"]);
        if ($enchantment === null) {
            $sender->sendMessage(TextFormat::RED . "Invalid enchantment.");
            return;
        }
        $sender->sendMessage(TextFormat::GREEN . $enchantment->getDisplayName() . TextFormat::EOL . TextFormat::RESET . "ID: " . $enchantment->getId() . TextFormat::EOL . "Description: " . $enchantment->getDescription() . TextFormat::EOL . "Type: " . Utils::TYPE_NAMES[$enchantment->getItemType()] . TextFormat::EOL . "Rarity: " . Utils::RARITY_NAMES[$enchantment->getRarity()] . TextFormat::EOL . "Max Level: " . $enchantment->getMaxLevel());
    }

    public function showInfo(Player $player, CustomEnchant $enchantment): void
    {
        $infoForm = new SimpleForm(function (Player $player, ?int $data): void {
            if ($data !== null) $this->plugin->getServer()->dispatchCommand($player, "ce");
        });
        $infoForm->setTitle(TextFormat::GREEN . $enchantment->getDisplayName() . " Enchantment");
        $infoForm->setContent(TextFormat::GREEN . $enchantment->getDisplayName() . TextFormat::EOL . TextFormat::RESET . "ID: " . $enchantment->getId() . TextFormat::EOL . "Description: " . $enchantment->getDescription() . TextFormat::EOL . "Type: " . Utils::TYPE_NAMES[$enchantment->getItemType()] . TextFormat::EOL . "Rarity: " . Utils::RARITY_NAMES[$enchantment->getRarity()] . TextFormat::EOL . "Max Level: " . $enchantment->getMaxLevel());
        $infoForm->addButton("Back");
        $player->sendForm($infoForm);
    }

    /**
     * @throws ArgumentOrderException
     */
    public function prepare(): void
    {
        $this->setPermission("piggycustomenchants.command.ce.list");
        $this->registerArgument(0, new RawStringArgument("enchantment", true));
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/ListSubCommand.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\commands\subcommands;

use CortexPE\Commando\BaseSubCommand;
use DaPigGuy\PiggyCustomEnchants\CustomEnchantManager;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use DaPigGuy\PiggyCustomEnchants\utils\Utils;
use jojoe77777\FormAPI\SimpleForm;
use pocketmine\command\CommandSender;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class ListSubCommand extends BaseSubCommand
{
    /** @var PiggyCustomEnchants */
    protected $plugin;

    public function onRun(CommandSender $sender, string $aliasUsed, array $args): void
    {
        if ($sender instanceof Player && $this->plugin->areFormsEnabled()) {
            $this->sendTypesForm($sender);
            return;
        }
        $sender->sendMessage($this->getCustomEnchantList());
    }

    /**
     * @return CustomEnchant[][]
     */
    public function getEnchantmentsByType(): array
    {
        $enchantmentsByType = [];
        foreach (CustomEnchantManager::getEnchantments() as $enchantment) {
            if (!isset($enchantmentsByType[$enchantment->getItemType()])) $enchantmentsByType[$enchantment->getItemType()] = [];
            $enchantmentsByType[$enchantment->getItemType()][] = $enchantment;
        }
        return array_map(function (array $typeEnchants) {
            uasort($typeEnchants, function (CustomEnchant $a, CustomEnchant $b) {
                return strcmp($a->getDisplayName(), $b->getDisplayName());
            });
            return $typeEnchants;
        }, $enchantmentsByType);
    }

    public function getCustomEnchantList(): string
    {
        $enchantmentsByType = $this->getEnchantmentsByType();
        $listString = "";
        foreach (Utils::TYPE_NAMES as $type => $name) {
            if (isset($enchantmentsByType[$type])) {
                $listString .= TextFormat::EOL . TextFormat::GREEN . TextFormat::BOLD . Utils::TYPE_NAMES[$type] . TextFormat::EOL . TextFormat::RESET;
                $listString .= implode(", ", array_map(function (CustomEnchant $enchant) {
                    return $enchant->getDisplayName();
                }, $enchantmentsByType[$type]));
            }
        }
        return $listString;
    }

    public function sendTypesForm(Player $player): void
    {
        $enchantmentsByType = $this->getEnchantmentsByType();
        $form = new SimpleForm(function (Player $player, ?int $data) use ($enchantmentsByType): void {
            if ($data !== null) {
                if ($data === count($enchantmentsByType)) {
                    $player->getServer()->dispatchCommand($player, "ce");
                    return;
                }
                $type = array_keys($enchantmentsByType)[$data];
                $this->sendEnchantsForm($player, $type);
            }
        });
        $form->setTitle(TextFormat::GREEN . "Custom Enchants List");
        foreach ($enchantmentsByType as $type => $enchantments) {
            $form->addButton(Utils::TYPE_NAMES[$type]);
        }
        $form->addButton("Back");
        $player->sendForm($form);
    }

    public function sendEnchantsForm(Player $player, int $type): void
    {
        $enchantmentsByType = $this->getEnchantmentsByType();
        $enchantForm = new SimpleForm(function (Player $player, ?int $data) use ($type, $enchantmentsByType): void {
            if ($data !== null) {
                if ($data === count($enchantmentsByType[$type])) {
                    $player->getServer()->dispatchCommand($player, "ce list");
                    return;
                }
                $infoForm = new SimpleForm(function (Player $player, ?int $data) use ($type): void {
                    if ($data !== null) $this->sendEnchantsForm($player, $type);
                });
                /** @var CustomEnchant $selectedEnchantment */
                $selectedEnchantment = array_values($enchantmentsByType[$type])[$data];
                $infoForm->setTitle(TextFormat::GREEN . $selectedEnchantment->getDisplayName() . " Enchantment");
                $infoForm->setContent(TextFormat::GREEN . $selectedEnchantment->getDisplayName() . TextFormat::EOL . TextFormat::RESET . "ID: " . $selectedEnchantment->getId() . TextFormat::EOL . "Description: " . $selectedEnchantment->getDescription() . TextFormat::EOL . "Type: " . Utils::TYPE_NAMES[$type] . TextFormat::EOL . "Rarity: " . Utils::RARITY_NAMES[$selectedEnchantment->getRarity()] . TextFormat::EOL . "Max Level: " . $selectedEnchantment->getMaxLevel());
                $infoForm->addButton("Back");
                $player->sendForm($infoForm);
            }
        });
        $enchantForm->setTitle(TextFormat::GREEN . Utils::TYPE_NAMES[$type] . " Enchants");
        foreach ($enchantmentsByType[$type] as $enchantment) {
            $enchantForm->addButton($enchantment->getDisplayName());
        }
        $enchantForm->addButton("Back");
        $player->sendForm($enchantForm);
    }

    public function prepare(): void
    {
        $this->setPermission("piggycustomenchants.command.ce.list");
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/NBTSubCommand.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\commands\subcommands;

use CortexPE\Commando\BaseSubCommand;
use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use pocketmine\command\CommandSender;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class NBTSubCommand extends BaseSubCommand
{
    /** @var PiggyCustomEnchants */
    protected $plugin;

    public function onRun(CommandSender $sender, string $aliasUsed, array $args): void
    {
        if ($sender instanceof Player) {
            $sender->sendMessage($sender->getInventory()->getItemInHand()->getNamedTag()->toString());
            return;
        }
        $sender->sendMessage(TextFormat::RED . "Please use this in-game.");
    }

    public function prepare(): void
    {
        $this->setPermission("piggycustomenchants.command.ce.nbt");
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/RemoveSubCommand.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\commands\subcommands;

use CortexPE\Commando\args\RawStringArgument;
use CortexPE\Commando\BaseSubCommand;
use CortexPE\Commando\exception\ArgumentOrderException;
use DaPigGuy\PiggyCustomEnchants\CustomEnchantManager;
use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use DaPigGuy\PiggyCustomEnchants\utils\Utils;
use jojoe77777\FormAPI\CustomForm;
use pocketmine\command\CommandSender;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class RemoveSubCommand extends BaseSubCommand
{
    /** @var PiggyCustomEnchants */
    protected $plugin;

    public function onRun(CommandSender $sender, string $aliasUsed, array $args): void
    {
        if ($sender instanceof Player && $this->plugin->areFormsEnabled() && !isset($args["enchantment"])) {
            $this->onRunForm($sender, $aliasUsed, $args);
            return;
        }
        if ((!$sender instanceof Player && empty($args["player"])) || !isset($args["enchantment"])) {
            $sender->sendMessage("Usage: /ce remove <enchantment> <player>");
            return;
        }
        $target = empty($args["player"]) ? $sender : $this->plugin->getServer()->getPlayerByPrefix($args["player"]);
        if (!$target instanceof Player) {
            $sender->sendMessage(TextFormat::RED . "Invalid player.");
            return;
        }
        $enchant = CustomEnchantManager::getEnchantmentByName($args["enchantment"]);
        if ($enchant === null) {
            $sender->sendMessage(TextFormat::RED . "Invalid enchantment.");
            return;
        }
        $item = $target->getInventory()->getItemInHand();
        if ($item->getEnchantment($enchant) === null) {
            $sender->sendMessage(TextFormat::RED . "Item does not have specified enchantment.");
            return;
        }
        $item->removeEnchantment($enchant);
        $sender->sendMessage(TextFormat::GREEN . "Enchantment successfully removed.");
        $target->getInventory()->setItemInHand($item);
    }

    public function onRunForm(CommandSender $sender, string $aliasUsed, array $args): void
    {
        if ($sender instanceof Player) {
            $form = new CustomForm(function (Player $player, ?array $data): void {
                if ($data !== null) {
                    $enchant = is_numeric($data[0]) ? CustomEnchantManager::getEnchantment((int)$data[0]) : CustomEnchantManager::getEnchantmentByName($data[0]);
                    if ($enchant == null) {
                        Utils::errorForm($player, TextFormat::RED . "Invalid enchantment.");
                        return;
                    }
                    $target = $this->plugin->getServer()->getPlayerByPrefix($data[1]);
                    if (!$target instanceof Player) {
                        Utils::errorForm($player, TextFormat::RED . "Invalid player.");
                        return;
                    }
                    $item = $target->getInventory()->getItemInHand();
                    if ($item->getEnchantment($enchant) === null) {
                        $player->sendMessage(TextFormat::RED . "Item does not have specified enchantment.");
                        return;
                    }
                    $item->removeEnchantment($enchant);
                    $target->sendMessage(TextFormat::GREEN . "Enchantment successfully removed.");
                    $target->getInventory()->setItemInHand($item);
                }
            });
            $form->setTitle(TextFormat::GREEN . "Remove Custom Enchantment");
            $form->addInput("Enchantment");
            $form->addInput("Player", "", $sender->getName());
            $sender->sendForm($form);
        }
    }

    /**
     * @throws ArgumentOrderException
     */
    protected function prepare(): void
    {
        $this->setPermission("piggycustomenchants.command.ce.remove");
        $this->registerArgument(0, new RawStringArgument("enchantment", true));
        $this->registerArgument(1, new RawStringArgument("player", true));
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/CustomEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants;

use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use DaPigGuy\PiggyCustomEnchants\utils\Utils;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\enchantment\ItemFlags;
use pocketmine\item\enchantment\Rarity;
use pocketmine\player\Player;
use ReflectionClass;

class CustomEnchant extends Enchantment
{
    public string $name = "";
    public int $rarity = Rarity::RARE;
    public int $maxLevel = 5;
    private string $displayName;
    public string $description;
    public array $extraData;
    public int $cooldownDuration;
    public int $chance;

    public int $usageType = CustomEnchant::TYPE_HAND;
    public int $itemType = CustomEnchant::ITEM_TYPE_WEAPON;

    /** @var int[] */
    public array $cooldown;

    const TYPE_HAND = 0;
    const TYPE_ANY_INVENTORY = 1;
    const TYPE_INVENTORY = 2;
    const TYPE_ARMOR_INVENTORY = 3;
    const TYPE_HELMET = 4;
    const TYPE_CHESTPLATE = 5;
    const TYPE_LEGGINGS = 6;
    const TYPE_BOOTS = 7;

    const ITEM_TYPE_GLOBAL = 0;
    const ITEM_TYPE_DAMAGEABLE = 1;
    const ITEM_TYPE_WEAPON = 2;
    const ITEM_TYPE_SWORD = 3;
    const ITEM_TYPE_BOW = 4;
    const ITEM_TYPE_TOOLS = 5;
    const ITEM_TYPE_PICKAXE = 6;
    const ITEM_TYPE_AXE = 7;
    const ITEM_TYPE_SHOVEL = 8;
    const ITEM_TYPE_HOE = 9;
    const ITEM_TYPE_ARMOR = 10;
    const ITEM_TYPE_HELMET = 11;
    const ITEM_TYPE_CHESTPLATE = 12;
    const ITEM_TYPE_LEGGINGS = 13;
    const ITEM_TYPE_BOOTS = 14;
    const ITEM_TYPE_COMPASS = 15;

    public function __construct(protected PiggyCustomEnchants $plugin, public int $id)
    {
        $this->rarity = array_flip(Utils::RARITY_NAMES)[ucfirst(strtolower($plugin->getEnchantmentData($this->name, "rarities", Utils::RARITY_NAMES[$this->rarity])))];
        $this->maxLevel = (int)$plugin->getEnchantmentData($this->name, "max_levels", $this->maxLevel);
        $this->displayName = (string)$plugin->getEnchantmentData($this->name, "display_names", $this->displayName ?? $this->name);
        $this->description = (string)$plugin->getEnchantmentData($this->name, "descriptions", $this->description ?? "");
        $this->extraData = $plugin->getEnchantmentData($this->name, "extra_data", $this->getDefaultExtraData());
        $this->cooldownDuration = (int)$plugin->getEnchantmentData($this->name, "cooldowns", $this->cooldownDuration ?? 0);
        $this->chance = (int)$plugin->getEnchantmentData($this->name, "chances", $this->chance ?? 100);
        foreach ($this->getDefaultExtraData() as $key => $value) {
            if (!isset($this->extraData[$key])) {
                $this->extraData[$key] = $value;
                $plugin->setEnchantmentData($this->name, "extra_data", $this->extraData);
            }
        }
        if (!Utils::isCoolKid($plugin->getDescription())) $this->id = (int)array_rand(array_flip((new ReflectionClass(CustomEnchantIds::class))->getConstants()));
        parent::__construct($this->name, $this->rarity, ItemFlags::ALL, ItemFlags::ALL, $this->maxLevel);
    }

    public function getId(): int
    {
        return $this->id;
    }

    public function getDisplayName(): string
    {
        return $this->displayName;
    }

    public function getDescription(): string
    {
        return $this->description;
    }

    public function getExtraData(): array
    {
        return $this->extraData;
    }

    public function getDefaultExtraData(): array
    {
        return [];
    }

    public function getUsageType(): int
    {
        return $this->usageType;
    }

    public function getItemType(): int
    {
        return $this->itemType;
    }

    public function getPriority(): int
    {
        return 1;
    }

    public function canReact(): bool
    {
        return false;
    }

    public function canTick(): bool
    {
        return false;
    }

    public function canToggle(): bool
    {
        return false;
    }

    public function getCooldown(Player $player): int
    {
        return ($this->cooldown[$player->getName()] ?? time()) - time();
    }

    public function setCooldown(Player $player, int $cooldown): void
    {
        $this->cooldown[$player->getName()] = time() + $cooldown;
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/CustomEnchantIds.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants;

class CustomEnchantIds
{
    /**
     * Global
     */
    const AUTOREPAIR = 108;
    const SOULBOUND = 118;

    /**
     * Weapons
     */
    const AERIAL = 114;
    const BACKSTAB = 122;
    const BLESSED = 120;
    const BLIND = 101;
    const CHARGE = 113;
    const CRIPPLE = 109;
    const DEATHBRINGER = 102;
    const DEEPWOUNDS = 112;
    const DISARMING = 117;
    const DISARMOR = 121;
    const GOOEY = 103;
    const HALLUCINATION = 119;
    //const HEADLESS = 116;
    //const ICEASPECT = 106;
    const LIFESTEAL = 100;
    const LIGHTNING = 123;
    const LUCKYCHARM = 124;
    const POISON = 104;
    //const SHOCKWAVE = 107;
    const VAMPIRE = 111;
    const WITHER = 115;

    /**
     * Sword
     */

    /**
     * Bows
     */
    const AUTOAIM = 306;
    const BLAZE = 311;
    const BOMBARDMENT = 300;
    const BOUNTYHUNTER = 309;
    //const FIREWORK = 302;
    const GRAPPLING = 313;
    const HEADHUNTER = 312;
    const HEALING = 310;
    const HOMING = 316;
    const MISSILE = 315;
    const MOLOTOV = 304;
    const PARALYZE = 303;
    const PIERCING = 307;
    const PORKIFIED = 314;
    const SHUFFLE = 308;
    const VOLLEY = 305;
    const WITHERSKULL = 301;

    /**
     * Tools
     */
    const DRILLER = 206;
    const ENERGIZING = 202;
    const EXPLOSIVE = 200;
    const HASTE = 207;
    const JACKPOT = 212;
    const OXYGENATE = 211;
    const QUICKENING = 203;
    const SMELTING = 201;
    const TELEPATHY = 205;

    /**
     * Pickaxes
     */

    /**
     * Axes
     */
    const LUMBERJACK = 204;

    /**
     * Shovels
     */

    /**
     * Hoes
     */
    const FARMER = 209;
    const FERTILIZER = 208;
    const HARVEST = 210;

    /**
     * Armor
     */
    const MOLTEN = 400;
    const ENLIGHTED = 401;
    const HARDENED = 402;
    const POISONED = 403;
    const FROZEN = 404;
    const OBSIDIANSHIELD = 405;
    const REVULSION = 406;
    const SELFDESTRUCT = 407;
    const CURSED = 408;
    const ENDERSHIFT = 409;
    const DRUNK = 410;
    const BERSERKER = 411;
    const CLOAKING = 412;
    const REVIVE = 413;
    const SHRINK = 414;
    const GROW = 415;
    const CACTUS = 416;
    const ANTIKNOCKBACK = 417;
    const FORCEFIELD = 418;
    const OVERLOAD = 419;
    const ARMORED = 420;
    const TANK = 421;
    const HEAVY = 422;
    const SHIELDED = 423;
    const POISONOUSCLOUD = 424;

    /**
     * Helmet
     */
    const ANTITOXIN = 604;
    const FOCUSED = 603;
    const GLOWING = 601;
    const IMPLANTS = 600;
    const MEDITATION = 602;

    /**
     * Chestplate
     */
    const CHICKEN = 801;
    const ENRAGED = 804;
    const PARACHUTE = 800;
    const PROWL = 802;
    const SPIDER = 803;
    const VACUUM = 805;

    /**
     * Leggings
     */

    /**
     * Boots
     */
    const GEARS = 500;
    const JETPACK = 503;
    const MAGMAWALKER = 504;
    const SPRINGS = 501;
    const STOMP = 502;

    /**
     * Compass
     */
    const RADAR = 700;
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/ReactiveEnchantment.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants;

use DaPigGuy\PiggyCustomEnchants\enchants\traits\ReactiveTrait;

class ReactiveEnchantment extends CustomEnchant
{
    use ReactiveTrait;
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/TickingEnchantment.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants;

use DaPigGuy\PiggyCustomEnchants\enchants\traits\TickingTrait;

class TickingEnchantment extends CustomEnchant
{
    use TickingTrait;
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/ToggleableEnchantment.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants;

use DaPigGuy\PiggyCustomEnchants\enchants\traits\ToggleTrait;

class ToggleableEnchantment extends CustomEnchant
{
    use ToggleTrait;
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/AntiKnockbackEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;

class AntiKnockbackEnchant extends ReactiveEnchantment
{
    public string $name = "Anti Knockback";
    public int $maxLevel = 1;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageByEntityEvent) {
            $stack = $stack > 4 ? 4 : $stack;
            $event->setKnockBack($event->getKnockBack() * (4 - $stack) / (5 - $stack));
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ArmoredEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\item\Sword;
use pocketmine\player\Player;

class ArmoredEnchant extends ReactiveEnchantment
{
    public string $name = "Armored";

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getDefaultExtraData(): array
    {
        return ["absorbedDamageMultiplier" => 0.2];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageByEntityEvent) {
            $damager = $event->getDamager();
            if ($damager instanceof Player) {
                if ($damager->getInventory()->getItemInHand() instanceof Sword) {
                    $event->setModifier(-($event->getFinalDamage() * $this->extraData["absorbedDamageMultiplier"] * $level), CustomEnchantIds::ARMORED);
                }
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/AttackerDeterrentEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use pocketmine\entity\effect\Effect;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\Living;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class AttackerDeterrentEnchant extends ReactiveEnchantment
{
    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    /**
     * @param Effect[] $effects
     * @param int[] $durationMultiplier
     * @param int[] $amplifierMultiplier
     */
    public function __construct(PiggyCustomEnchants $plugin, int $id, string $name, private array $effects, private array $durationMultiplier, private array $amplifierMultiplier, int $rarity = Rarity::RARE)
    {
        $this->name = $name;
        $this->rarity = $rarity;
        parent::__construct($plugin, $id);
    }

    public function getDefaultExtraData(): array
    {
        return ["durationMultipliers" => $this->durationMultiplier, "amplifierMultipliers" => $this->amplifierMultiplier];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageByEntityEvent) {
            $damager = $event->getDamager();
            if ($damager instanceof Living) {
                foreach ($this->effects as $key => $effect) {
                    $damager->getEffects()->add(new EffectInstance($effect, $this->extraData["durationMultipliers"][$key] * $level, $this->extraData["amplifierMultipliers"][$key] * $level));
                }
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/BerserkerEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;

class BerserkerEnchant extends ReactiveEnchantment
{
    public string $name = "Berserker";
    public int $cooldownDuration = 300;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getReagent(): array
    {
        return [EntityDamageEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["minimumHealth" => 4, "effectDurationMultiplier" => 200, "effectAmplifierBase" => 3, "effectAmplifierMultiplier" => 1];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageEvent) {
            if ($player->getHealth() - $event->getFinalDamage() <= $this->extraData["minimumHealth"]) {
                if (!$player->getEffects()->has(VanillaEffects::STRENGTH())) {
                    $effect = new EffectInstance(VanillaEffects::STRENGTH(), $this->extraData["effectDurationMultiplier"] * $level, $level * $this->extraData["effectAmplifierMultiplier"] + $this->extraData["effectAmplifierBase"], false);
                    $player->getEffects()->add($effect);
                }
                $player->sendMessage("Your bloodloss makes your stronger!");
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/CactusEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\TickingEnchantment;
use DaPigGuy\PiggyCustomEnchants\utils\AllyChecks;
use pocketmine\entity\Living;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;

class CactusEnchant extends TickingEnchantment
{
    public string $name = "Cactus";
    public int $maxLevel = 1;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getTickingInterval(): int
    {
        return 10;
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        foreach ($player->getWorld()->getNearbyEntities($player->getBoundingBox()->expandedCopy(1, 0, 1), $player) as $entity) {
            if ($entity instanceof Living && !AllyChecks::isAlly($player, $entity)) {
                $ev = new EntityDamageByEntityEvent($player, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
                $entity->attack($ev);
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/CloakingEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class CloakingEnchant extends ReactiveEnchantment
{
    public string $name = "Cloaking";
    public int $rarity = Rarity::UNCOMMON;
    public int $cooldownDuration = 10;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getDefaultExtraData(): array
    {
        return ["durationMultiplier" => 60];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageByEntityEvent) {
            $player->getEffects()->add(new EffectInstance(VanillaEffects::INVISIBILITY(), $this->extraData["durationMultiplier"] * $level, 0, false));
            $player->sendMessage(TextFormat::DARK_GRAY . "You have become invisible!");
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/EndershiftEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;

class EndershiftEnchant extends ReactiveEnchantment
{
    public string $name = "Endershift";
    public int $cooldownDuration = 300;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getReagent(): array
    {
        return [EntityDamageEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["speedDurationMultiplier" => 200, "speedBaseAmplifier" => 3, "speedAmplifierMultiplier" => 1, "strengthDurationMultiplier" => 200, "strengthBaseAmplifier" => 3, "strengthAmplifierMultiplier" => 1];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageEvent) {
            if ($player->getHealth() - $event->getFinalDamage() <= 4) {
                if (!$player->getEffects()->has(VanillaEffects::SPEED())) {
                    $effect = new EffectInstance(VanillaEffects::SPEED(), $this->extraData["speedDurationMultiplier"] * $level, $level * $this->extraData["speedAmplifierMultiplier"] + $this->extraData["speedBaseAmplifier"], false);
                    $player->getEffects()->add($effect);
                }
                if (!$player->getEffects()->has(VanillaEffects::ABSORPTION())) {
                    $effect = new EffectInstance(VanillaEffects::ABSORPTION(), $this->extraData["strengthDurationMultiplier"] * $level, $level * $this->extraData["strengthAmplifierMultiplier"] + $this->extraData["strengthBaseAmplifier"], false);
                    $player->getEffects()->add($effect);
                }
                $player->sendMessage("You feel a rush of energy coming from your armor!");
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/EnlightedEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class EnlightedEnchant extends ReactiveEnchantment
{
    public string $name = "Enlighted";
    public int $rarity = Rarity::UNCOMMON;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getDefaultExtraData(): array
    {
        return ["durationMultiplier" => 60, "baseAmplifier" => 0, "amplifierMultiplier" => 1];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageByEntityEvent) {
            $player->getEffects()->add(new EffectInstance(VanillaEffects::REGENERATION(), $this->extraData["durationMultiplier"] * $level, $level * $this->extraData["amplifierMultiplier"] + $this->extraData["baseAmplifier"], false));
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ForcefieldEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\TickingTrait;
use DaPigGuy\PiggyCustomEnchants\utils\AllyChecks;
use pocketmine\entity\object\ExperienceOrb;
use pocketmine\entity\object\ItemEntity;
use pocketmine\entity\projectile\Projectile;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\particle\EnchantmentTableParticle;

class ForcefieldEnchant extends ToggleableEnchantment
{
    use TickingTrait;

    public string $name = "Forcefield";
    public int $rarity = Rarity::MYTHIC;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getDefaultExtraData(): array
    {
        return ["radiusMultiplier" => 0.75];
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        $forcefieldLevel = $this->getStack($player);
        if ($forcefieldLevel > 0) {
            $radius = $forcefieldLevel * $this->extraData["radiusMultiplier"];
            $entities = $player->getWorld()->getNearbyEntities($player->getBoundingBox()->expandedCopy($radius, $radius, $radius), $player);
            foreach ($entities as $entity) {
                if ($entity instanceof Projectile) {
                    if ($entity->getOwningEntity() !== $player) $entity->setMotion($entity->getMotion()->multiply(-1));
                } else {
                    if (!$entity instanceof ItemEntity && !$entity instanceof ExperienceOrb && !AllyChecks::isAlly($player, $entity)) {
                        $entity->setMotion(new Vector3($player->getPosition()->subtractVector($entity->getPosition())->normalize()->multiply(-0.75)->x, 0, $player->getPosition()->subtractVector($entity->getPosition())->normalize()->multiply(-0.75)->z));
                    }
                }
            }
            if ($player->getServer()->getTick() % 5 === 0) {
                $diff = $radius / $forcefieldLevel;
                for ($theta = 0; $theta <= 360; $theta += $diff) {
                    $player->getWorld()->addParticle($player->getPosition()->add($radius * sin($theta), 0.5, $radius * cos($theta)), new EnchantmentTableParticle());
                }
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/GrowEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\ReactiveTrait;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\TickingTrait;
use pocketmine\event\Event;
use pocketmine\event\player\PlayerToggleSneakEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class GrowEnchant extends ToggleableEnchantment
{
    use ReactiveTrait {
        onReaction as protected originalOnReaction;
    }
    use TickingTrait;

    public string $name = "Grow";
    public int $rarity = Rarity::UNCOMMON;
    public int $cooldownDuration = 75;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    /** @var Player[] */
    public array $grew;
    /** @var int[] */
    public array $growPower;
    /** @var bool[] */
    public array $shiftCache;

    public function getReagent(): array
    {
        return [PlayerToggleSneakEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["power" => 60 * 20, "base" => 0.3, "multiplier" => 0.0125];
    }

    public function onReaction(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof PlayerToggleSneakEvent) {
            $playerName = $player->getName();
            if ($event->isSneaking()) {
                if (!isset($this->shiftCache[$playerName])) {
                    $this->originalOnReaction($player, $item, $inventory, $slot, $event, $level, $stack);
                    if (isset($this->grew[$playerName])) $this->setCooldown($player, 0);
                    $this->shiftCache[$playerName] = true;
                } else {
                    $player->sendTip(TextFormat::RED . "Grow is still in cooldown: " . $this->getCooldown($player) . "s");
                }
            } elseif (isset($this->shiftCache[$playerName])) {
                unset($this->shiftCache[$playerName]);
            }
        }
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof PlayerToggleSneakEvent) {
            $playerName = $player->getName();
            if ($this->getArmorStack($player) === 4) {
                if ($event->isSneaking()) {
                    if ($stack - $level === 0) {
                        if (isset($this->grew[$playerName])) {
                            unset($this->grew[$playerName]);
                            $player->setScale(1);
                            $player->sendTip(TextFormat::RED . "You have shrunk back to normal size.");
                        } else {
                            $this->grew[$playerName] = $player;
                            if (!isset($this->growPower[$playerName])) $this->growPower[$playerName] = $this->extraData["power"];
                            $player->setScale($player->getScale() + $this->extraData["base"] + ($this->getStack($player) * $this->extraData["multiplier"]));
                            $player->sendTip(TextFormat::GREEN . "You have grown. Sneak again to shrink back to normal size.");
                        }
                    }
                }
            }
        }
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        $playerName = $player->getName();
        if (isset($this->grew[$playerName])) {
            $this->growPower[$playerName]--;
            $player->sendTip(TextFormat::GREEN . "Grow power remaining: " . $this->growPower[$playerName]);
            if ($this->getArmorStack($player) < 4 || $this->growPower[$playerName] <= 0) {
                unset($this->grew[$playerName]);
                $this->setCooldown($player, $this->getCooldownDuration());
                if ($this->growPower[$playerName] <= 0) $this->growPower[$playerName] = $this->extraData["power"];
                $player->setScale(1);
                $player->sendTip(TextFormat::RED . "You have shrunk back to normal size.");
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/HeavyEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\item\ItemIds;
use pocketmine\player\Player;

class HeavyEnchant extends ReactiveEnchantment
{
    public string $name = "Heavy";

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getDefaultExtraData(): array
    {
        return ["absorbedDamageMultiplier" => 0.2];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageByEntityEvent) {
            $damager = $event->getDamager();
            if ($damager instanceof Player) {
                if ($damager->getInventory()->getItemInHand()->getId() === ItemIds::BOW) {
                    $event->setModifier(-($event->getFinalDamage() * $this->extraData["absorbedDamageMultiplier"] * $level), CustomEnchantIds::HEAVY);
                }
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/MoltenEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\entity\Living;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;

class MoltenEnchant extends ReactiveEnchantment
{
    public string $name = "Molten";

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getDefaultExtraData(): array
    {
        return ["durationMultiplier" => 3];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageByEntityEvent) {
            $damager = $event->getDamager();
            if ($damager instanceof Living) {
                $damager->setOnFire(($duration = $this->extraData["durationMultiplier"] * $level) > 1638 ? 1638 : $duration);
            }
        }
    }
}


================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/OverloadEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class OverloadEnchant extends ToggleableEnchantment
{
    public string $name = "Overload";
    public int $rarity = Rarity::MYTHIC;
    public int $maxLevel = 3;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getDefaultExtraData(): array
    {
        return ["multiplier" => 2];
    }

    public function toggle(Player $player, Item $item, Inventory $inventory, int $slot, int $level, bool $toggle): void
    {
        $player->setMaxHealth($player->getMaxHealth() + $this->extraData["multiplier"] * $level * ($toggle ? 1 : -1));
        $player->setHealth($player->getHealth() * ($player->getMaxHealth() / ($player->getMaxHealth() - $this->extraData["multiplier"] * $level * ($toggle ? 1 : -1))));
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/PoisonousCloudEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\TickingEnchantment;
use DaPigGuy\PiggyCustomEnchants\utils\AllyChecks;
use pocketmine\color\Color;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\entity\Living;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;
use pocketmine\world\particle\DustParticle;

class PoisonousCloudEnchant extends TickingEnchantment
{
    public string $name = "Poisonous Cloud";
    public int $maxLevel = 3;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getDefaultExtraData(): array
    {
        return ["radiusMultiplier" => 3, "durationMultiplier" => 100, "baseAmplifier" => -1, "amplifierMultiplier" => 1];
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        $radius = $level * $this->extraData["radiusMultiplier"];
        foreach ($player->getWorld()->getEntities() as $entity) {
            if ($entity !== $player && $entity instanceof Living && !AllyChecks::isAlly($player, $entity) && $entity->getPosition()->distance($player->getPosition()) <= $radius) {
                $effect = new EffectInstance(VanillaEffects::POISON(), $level * $this->extraData["durationMultiplier"], $level * $this->extraData["amplifierMultiplier"] + $this->extraData["baseAmplifier"], false);
                $entity->getEffects()->add($effect);
            }
        }
        if ($player->getServer()->getTick() % 20 === 0) {
            for ($x = -$radius; $x <= $radius; $x += 0.25) {
                for ($y = -$radius; $y <= $radius; $y += 0.25) {
                    for ($z = -$radius; $z <= $radius; $z += 0.25) {
                        $random = mt_rand(1, 800 * $level);
                        if ($random === 800 * $level) {
                            $player->getWorld()->addParticle($player->getPosition()->add($x, $y, $z), new DustParticle(new Color(34, 139, 34)));
                        }
                    }
                }
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ReviveEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\CustomEnchantManager;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\enchantment\EnchantmentInstance;
use pocketmine\item\Item;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;
use pocketmine\world\particle\FlameParticle;

class ReviveEnchant extends ReactiveEnchantment
{
    public string $name = "Revive";

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getReagent(): array
    {
        return [EntityDamageEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["nauseaDuration" => 600, "slownessDuration" => 600];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageEvent) {
            if ($event->getFinalDamage() >= $player->getHealth()) {
                $level > 1 ? $item->addEnchantment(new EnchantmentInstance(CustomEnchantManager::getEnchantment(CustomEnchantIds::REVIVE), $level - 1)) : $item->removeEnchantment(CustomEnchantManager::getEnchantment(CustomEnchantIds::REVIVE));
                $player->getArmorInventory()->setItem($slot, $item);

                $player->getEffects()->clear();
                $player->setHealth($player->getMaxHealth());
                $player->getHungerManager()->setFood($player->getHungerManager()->getMaxFood());
                $player->getXpManager()->setXpAndProgress(0, 0.0);

                $effect = new EffectInstance(VanillaEffects::NAUSEA(), $this->extraData["nauseaDuration"], 0, false);
                $player->getEffects()->add($effect);
                $effect = new EffectInstance(VanillaEffects::SLOWNESS(), $this->extraData["slownessDuration"], 0, false);
                $player->getEffects()->add($effect);

                for ($i = $player->getPosition()->y; $i <= 256; $i += 0.25) {
                    $player->getWorld()->addParticle($player->getPosition()->add(0, $i - $player->getPosition()->y, 0), new FlameParticle());
                }
                $player->sendTip(TextFormat::GREEN . "You were revived.");

                foreach ($event->getModifiers() as $modifier => $damage) {
                    $event->setModifier(0, $modifier);
                }
                $event->setBaseDamage(0);
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/SelfDestructEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use DaPigGuy\PiggyCustomEnchants\entities\PiggyTNT;
use pocketmine\event\Event;
use pocketmine\event\player\PlayerDeathEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\utils\Random;

class SelfDestructEnchant extends ReactiveEnchantment
{
    public string $name = "Self Destruct";

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getReagent(): array
    {
        return [PlayerDeathEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["tntAmountMultiplier" => 1];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof PlayerDeathEvent) {
            for ($i = 0; $i < $level * $this->extraData["tntAmountMultiplier"]; $i++) {
                $random = new Random();
                $tnt = new PiggyTNT($player->getLocation(), null, $this->plugin->getConfig()->getNested("world-damage.self-destruct", false));
                $tnt->setFuse(40);
                $tnt->setOwningEntity($player);
                $tnt->setMotion(new Vector3($random->nextFloat() * 1.5 - 1, $random->nextFloat() * 1.5, $random->nextFloat() * 1.5 - 1));
                $tnt->spawnToAll();
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ShieldedEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;

class ShieldedEnchant extends ToggleableEnchantment
{
    public string $name = "Shielded";
    public int $maxLevel = 3;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    /** @var EffectInstance[] */
    private array $previousEffect;

    public function toggle(Player $player, Item $item, Inventory $inventory, int $slot, int $level, bool $toggle): void
    {
        if ($toggle) {
            if ($player->getEffects()->has(VanillaEffects::RESISTANCE()) && $player->getEffects()->get(VanillaEffects::RESISTANCE())->getAmplifier() > $this->getStack($player) - 1) $this->previousEffect[$player->getName()] = $player->getEffects()->get(VanillaEffects::RESISTANCE());
        } else {
            if ($this->getArmorStack($player) === 0) {
                $player->getEffects()->remove(VanillaEffects::RESISTANCE());
                if (isset($this->previousEffect[$player->getName()])) {
                    $player->getEffects()->add($this->previousEffect[$player->getName()]);
                    unset($this->previousEffect[$player->getName()]);
                }
                return;
            }
        }
        $player->getEffects()->remove(VanillaEffects::RESISTANCE());
        $player->getEffects()->add(new EffectInstance(VanillaEffects::RESISTANCE(), 2147483647, $this->getStack($player) - 1, false));
    }

    public function canEffectsStack(): bool
    {
        return true;
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ShrinkEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\ReactiveTrait;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\TickingTrait;
use pocketmine\event\Event;
use pocketmine\event\player\PlayerToggleSneakEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class ShrinkEnchant extends ToggleableEnchantment
{
    use ReactiveTrait {
        onReaction as protected originalOnReaction;
    }
    use TickingTrait;

    public string $name = "Shrink";
    public int $rarity = Rarity::UNCOMMON;
    public int $maxLevel = 2;
    public int $cooldownDuration = 75;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    /** @var Player[] */
    public array $shrunk;
    /** @var int[] */
    public array $shrinkPower;
    /** @var bool[] */
    public array $shiftCache;

	/**
	 * @return class-string[]
	 */
	public function getReagent(): array
    {
        return [PlayerToggleSneakEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["power" => 60 * 20, "base" => 0.7, "multiplier" => 0.0125];
    }

    public function onReaction(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof PlayerToggleSneakEvent) {
            $playerName = $player->getName();
            if ($event->isSneaking()) {
                if (!isset($this->shiftCache[$playerName])) {
                    $this->originalOnReaction($player, $item, $inventory, $slot, $event, $level, $stack);
                    if (isset($this->shrunk[$playerName])) $this->setCooldown($player, 0);
                    $this->shiftCache[$playerName] = true;
                } else {
                    $player->sendTip(TextFormat::RED . "Shrink is still in cooldown: " . $this->getCooldown($player) . "s");
                }
            } elseif (isset($this->shiftCache[$playerName])) {
                unset($this->shiftCache[$playerName]);
            }
        }
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof PlayerToggleSneakEvent) {
            $playerName = $player->getName();
            if ($this->getArmorStack($player) === 4) {
                if ($event->isSneaking()) {
                    if ($stack - $level === 0) {
                        if (isset($this->shrunk[$playerName])) {
                            unset($this->shrunk[$playerName]);
                            $player->setScale(1);
                            $player->sendTip(TextFormat::RED . "You have grown back to normal size.");
                        } else {
                            $this->shrunk[$playerName] = $player;
                            if (!isset($this->shrinkPower[$playerName])) $this->shrinkPower[$playerName] = $this->extraData["power"];
                            $player->setScale($player->getScale() - $this->extraData["base"] - ($this->getStack($player) * $this->extraData["multiplier"]));
                            $player->sendTip(TextFormat::GREEN . "You have shrunk. Sneak again to grow back to normal size.");
                        }
                    }
                }
            }
        }
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        $playerName = $player->getName();
        if (isset($this->shrunk[$playerName])) {
            $this->shrinkPower[$playerName]--;
            $player->sendTip(TextFormat::GREEN . "Shrink power remaining: " . $this->shrinkPower[$playerName]);
            if ($this->getArmorStack($player) < 4 || $this->shrinkPower[$playerName] <= 0) {
                unset($this->shrunk[$playerName]);
                $this->setCooldown($player, $this->getCooldownDuration());
                if ($this->shrinkPower[$playerName] <= 0) $this->shrinkPower[$playerName] = $this->extraData["power"];
                $player->setScale(1);
                $player->sendTip(TextFormat::RED . "You have grown back to normal size.");
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/TankEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\Axe;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class TankEnchant extends ReactiveEnchantment
{
    public string $name = "Tank";
    public int $rarity = Rarity::UNCOMMON;

    public int $usageType = CustomEnchant::TYPE_ARMOR_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_ARMOR;

    public function getDefaultExtraData(): array
    {
        return ["absorbedDamageMultiplier" => 0.2];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageByEntityEvent) {
            $damager = $event->getDamager();
            if ($damager instanceof Player) {
                if ($damager->getInventory()->getItemInHand() instanceof Axe) {
                    $event->setModifier(-($event->getFinalDamage() * $this->extraData["absorbedDamageMultiplier"] * $level), CustomEnchantIds::TANK);
                }
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/boots/JetpackEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\boots;

use DaPigGuy\PiggyCustomEnchants\CustomEnchantManager;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\TickingTrait;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\ToggleTrait;
use DaPigGuy\PiggyCustomEnchants\particles\JetpackParticle;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\Event;
use pocketmine\event\player\PlayerToggleSneakEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\Item;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class JetpackEnchant extends ReactiveEnchantment
{
    use TickingTrait;
    use ToggleTrait;

    public string $name = "Jetpack";
    public int $maxLevel = 3;

    public int $usageType = CustomEnchant::TYPE_BOOTS;
    public int $itemType = CustomEnchant::ITEM_TYPE_BOOTS;

    /** @var Player[] */
    public $activeJetpacks = [];

    /** @var array */
    public $powerRemaining;
    /** @var array */
    public $lastActivated;

    public function getReagent(): array
    {
        return [PlayerToggleSneakEvent::class, EntityDamageEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["power" => 300, "rechargeAmount" => 0.66, "enableAmount" => 25, "drainMultiplier" => 1, "sprintDrainMultiplier" => 1.25, "speedMultiplier" => 1, "sprintSpeedMultiplier" => 1.25];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageEvent && $event->getCause() === EntityDamageEvent::CAUSE_FALL && $this->hasActiveJetpack($player)) $event->cancel();
        if ($event instanceof PlayerToggleSneakEvent) {
            if ($event->isSneaking()) {
                if ($this->hasActiveJetpack($player)) {
                    if (!$player->isOnGround() && $player->getArmorInventory()->getChestplate()->getEnchantment(CustomEnchantManager::getEnchantment(CustomEnchantIds::PARACHUTE)) === null && !$player->getAllowFlight()) {
                        $player->sendPopup(TextFormat::RED . "It is unsafe to disable your jetpack while in the air.");
                    } else {
                        $this->powerActiveJetpack($player, false);
                    }
                } else {
                    $this->powerActiveJetpack($player);
                }
            }
        }
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        if ($this->hasActiveJetpack($player)) {
            $player->setMotion($player->getDirectionVector()->multiply($level * ($player->isSprinting() ? $this->extraData["sprintSpeedMultiplier"] : $this->extraData["speedMultiplier"])));
            $player->resetFallDistance();
            $player->getWorld()->addParticle($player->getPosition(), new JetpackParticle());
            $time = ceil($this->powerRemaining[$player->getName()] / 10);
            if ($time > 2) $player->sendTip(($time > 10 ? TextFormat::GREEN : ($time > 5 ? TextFormat::YELLOW : TextFormat::RED)) . "Power: " . str_repeat("|", (int)$time));
            $lowTime = ceil($this->powerRemaining[$player->getName()] / 5);
            if ($time <= 2 && $lowTime > 0) $player->sendTip(TextFormat::RED . "Jetpack low on power: " . str_repeat("|", (int)$lowTime));
            if ($player->getServer()->getTick() % 20 === 0) {
                $this->powerRemaining[$player->getName()] -= ($player->isSprinting() ? $this->extraData["sprintDrainMultiplier"] : $this->extraData["drainMultiplier"]);
                if ($this->powerRemaining[$player->getName()] <= 0) {
                    $player->sendTip(TextFormat::RED . "Jetpack has run out of power.");
                    $this->powerActiveJetpack($player, false);
                }
            }
        }
    }

    public function toggle(Player $player, Item $item, Inventory $inventory, int $slot, int $level, bool $toggle): void
    {
        if (!$toggle && $this->hasActiveJetpack($player)) $this->powerActiveJetpack($player, false);
    }

    public function hasActiveJetpack(Player $player): bool
    {
        return isset($this->activeJetpacks[$player->getName()]);
    }

    public function powerActiveJetpack(Player $player, bool $power = true): void
    {
        if ($power) {
            if (!isset($this->powerRemaining[$player->getName()])) {
                $this->powerRemaining[$player->getName()] = $this->extraData["power"];
                $this->activeJetpacks[$player->getName()] = $player;
            } else {
                $this->powerRemaining[$player->getName()] += (time() - $this->lastActivated[$player->getName()]) * $this->extraData["rechargeAmount"];
                if ($this->powerRemaining[$player->getName()] > $this->extraData["power"]) $this->powerRemaining[$player->getName()] = $this->extraData["power"];
                if ($this->powerRemaining[$player->getName()] < $this->extraData["enableAmount"]) {
                    $player->sendTip(TextFormat::RED . "Jetpack needs to charge up to " . $this->extraData["enableAmount"] . " before it can be re-enabled. (" . round(abs($this->powerRemaining[$player->getName()]), 2) . " / " . $this->extraData["power"] . ")");
                    return;
                }
                $this->activeJetpacks[$player->getName()] = $player;
            }
        } else {
            unset($this->activeJetpacks[$player->getName()]);
            $this->lastActivated[$player->getName()] = time();
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/boots/MagmaWalkerEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\boots;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\block\BlockFactory;
use pocketmine\block\BlockLegacyIds;
use pocketmine\block\Lava;
use pocketmine\event\Event;
use pocketmine\event\player\PlayerMoveEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class MagmaWalkerEnchant extends ReactiveEnchantment
{
    public string $name = "Magma Walker";
    public int $rarity = Rarity::UNCOMMON;
    public int $maxLevel = 2;

    public int $usageType = CustomEnchant::TYPE_BOOTS;
    public int $itemType = CustomEnchant::ITEM_TYPE_BOOTS;

    public function getReagent(): array
    {
        return [PlayerMoveEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["baseRadius" => 2, "radiusMultiplier" => 1];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof PlayerMoveEvent) {
            $world = $player->getWorld();
            if (!($world->getBlock($player->getPosition()->asVector3()) instanceof Lava)) {
                $radius = $level * $this->extraData["radiusMultiplier"] + $this->extraData["baseRadius"];
                for ($x = -$radius; $x <= $radius; $x++) {
                    for ($z = -$radius; $z <= $radius; $z++) {
                        $b = $world->getBlock($player->getPosition()->add($x, -1, $z));
                        if ($world->getBlock($b->getPosition()->add(0, 1, 0))->getId() === BlockLegacyIds::AIR) {
                            if ($b instanceof Lava && $b->getMeta() === 0) {
                                $world->setBlock($b->getPosition()->asVector3(), BlockFactory::getInstance()->get(BlockLegacyIds::OBSIDIAN, 15));
                            }
                        }
                    }
                }
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/boots/StompEnchantment.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\boots;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class StompEnchantment extends ReactiveEnchantment
{
    public string $name = "Stomp";
    public int $rarity = Rarity::UNCOMMON;
    public int $maxLevel = 1;

    public int $usageType = CustomEnchant::TYPE_BOOTS;
    public int $itemType = CustomEnchant::ITEM_TYPE_BOOTS;

    public function getReagent(): array
    {
        return [EntityDamageEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["redistributedDamageMultiplier" => 0.5, "absorbedDamageMultiplier" => 0.75];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityDamageEvent) {
            if ($event->getCause() === EntityDamageEvent::CAUSE_FALL) {
                $entities = $player->getWorld()->getNearbyEntities($player->getBoundingBox());
                foreach ($entities as $entity) {
                    if ($player === $entity) {
                        continue;
                    }
                    $ev = new EntityDamageByEntityEvent($player, $entity, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $event->getFinalDamage() * $this->extraData["redistributedDamageMultiplier"]);
                    $entity->attack($ev);
                }
                $event->setModifier(-($event->getFinalDamage() * $this->extraData["absorbedDamageMultiplier"] * count($entities)), CustomEnchantIds::STOMP);
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/ChickenEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\chestplate;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\TickingEnchantment;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\VanillaItems;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class ChickenEnchant extends TickingEnchantment
{
    public string $name = "Chicken";
    public int $rarity = Rarity::UNCOMMON;

    public int $usageType = CustomEnchant::TYPE_CHESTPLATE;
    public int $itemType = CustomEnchant::ITEM_TYPE_CHESTPLATE;

    public function getDefaultExtraData(): array
    {
        return ["treasureChanceMultiplier" => 5, "treasures" => ["266:0:1"], "interval" => 1200 * 5];
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        if (mt_rand(0, 100) <= $this->extraData["treasureChanceMultiplier"] * $level) {
            $drops = $this->plugin->getConfig()->getNested("chicken.drops", $this->extraData["treasures"]);
            if (!is_array($drops)) {
                $drops = [$drops];
            }
            $drop = array_rand($drops);
            $drop = explode(":", $drops[$drop]);
            $item = count($drop) < 3 ? VanillaItems::GOLD_INGOT() : ItemFactory::getInstance()->get((int)$drop[0], (int)$drop[1], (int)$drop[2]);
            $vowels = ["a", "e", "i", "o", "u"];
            $player->getWorld()->dropItem($player->getPosition(), $item, $player->getDirectionVector()->multiply(-0.4));
            $player->sendTip(TextFormat::GREEN . "You have laid a" . (in_array(strtolower($item->getName()[0]), $vowels) ? "n " : " ") . $item->getName() . "...");
        } else {
            $player->getWorld()->dropItem($player->getPosition(), VanillaItems::EGG(), $player->getDirectionVector()->multiply(-0.4));
            $player->sendTip(TextFormat::GREEN . "You have laid an egg.");
        }
    }

    public function getTickingInterval(): int
    {
        return $this->extraData["interval"];
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/ParachuteEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\chestplate;

use DaPigGuy\PiggyCustomEnchants\CustomEnchantManager;
use DaPigGuy\PiggyCustomEnchants\enchants\armor\boots\JetpackEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\TickingEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\ToggleTrait;
use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use pocketmine\block\BlockLegacyIds;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class ParachuteEnchant extends TickingEnchantment
{
    use ToggleTrait;

    public string $name = "Parachute";
    public int $rarity = Rarity::UNCOMMON;
    public int $maxLevel = 1;

    public int $usageType = CustomEnchant::TYPE_CHESTPLATE;
    public int $itemType = CustomEnchant::ITEM_TYPE_CHESTPLATE;

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        if ($this->isInAir($player) && !$player->getAllowFlight() && !$player->canClimbWalls() && (($enchantInstance = $player->getArmorInventory()->getBoots()->getEnchantment(CustomEnchantManager::getEnchantment(CustomEnchantIds::JETPACK))) === null || !($enchant = $enchantInstance->getType()) instanceof JetpackEnchant || !$enchant->hasActiveJetpack($player))) {
            $player->getEffects()->add(new EffectInstance(PiggyCustomEnchants::$SLOW_FALL, 2147483647, 1, false));
        } elseif ($player->getEffects()->get(PiggyCustomEnchants::$SLOW_FALL) !== null) {
            if ($this->isInAir($player) || $player->getWorld()->getBlock($player->getPosition()->subtract(0, 1, 0))->getId() !== BlockLegacyIds::AIR) $player->getEffects()->remove(PiggyCustomEnchants::$SLOW_FALL);
        }
        $player->resetFallDistance();
    }

    public function toggle(Player $player, Item $item, Inventory $inventory, int $slot, int $level, bool $toggle): void
    {
        if (!$toggle && ($effect = $player->getEffects()->get(PiggyCustomEnchants::$SLOW_FALL)) !== null && $effect->getAmplifier() === -5) {
            $player->getEffects()->remove(PiggyCustomEnchants::$SLOW_FALL);
        }
    }

    public function isInAir(Player $player): bool
    {
        for ($y = 1; $y <= 5; $y++) {
            if ($player->getWorld()->getBlock($player->getPosition()->subtract(0, $y, 0))->getId() !== BlockLegacyIds::AIR) return false;
        }
        return true;
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/ProwlEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\chestplate;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\TickingTrait;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;

class ProwlEnchant extends ToggleableEnchantment
{
    use TickingTrait;

    public string $name = "Prowl";
    public int $maxLevel = 1;

    public int $usageType = CustomEnchant::TYPE_CHESTPLATE;
    public int $itemType = CustomEnchant::ITEM_TYPE_CHESTPLATE;

    /** @var bool[] */
    public array $prowled;

    public function toggle(Player $player, Item $item, Inventory $inventory, int $slot, int $level, bool $toggle): void
    {
        if (!$toggle && isset($this->prowled[$player->getName()])) {
            foreach ($player->getServer()->getOnlinePlayers() as $p) {
                $p->showPlayer($player);
            }
            $player->getEffects()->remove(VanillaEffects::SLOWNESS());
            if (!$player->getEffects()->has(VanillaEffects::INVISIBILITY())) {
                $player->setInvisible(false);
            }
            unset($this->prowled[$player->getName()]);
        }
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        if ($player->isSneaking()) {
            foreach ($player->getServer()->getOnlinePlayers() as $p) {
                $p->hidePlayer($player);
            }
            $effect = new EffectInstance(VanillaEffects::SLOWNESS(), 2147483647, 0, false);
            $player->setInvisible();
            $player->getEffects()->add($effect);
            $this->prowled[$player->getName()] = true;
        } else {
            if (isset($this->prowled[$player->getName()])) {
                foreach ($player->getServer()->getOnlinePlayers() as $p) {
                    $p->showPlayer($player);
                }
                $player->getEffects()->remove(VanillaEffects::SLOWNESS());
                if (!$player->getEffects()->has(VanillaEffects::INVISIBILITY())) {
                    $player->setInvisible(false);
                }
                unset($this->prowled[$player->getName()]);
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/SpiderEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\chestplate;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\TickingTrait;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;

class SpiderEnchant extends ToggleableEnchantment
{
    use TickingTrait;

    public string $name = "Spider";
    public int $maxLevel = 1;

    public int $usageType = CustomEnchant::TYPE_CHESTPLATE;
    public int $itemType = CustomEnchant::ITEM_TYPE_CHESTPLATE;


    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        $player->setCanClimbWalls($this->canClimb($player));
    }

    public function toggle(Player $player, Item $item, Inventory $inventory, int $slot, int $level, bool $toggle): void
    {
        if (!$toggle) $player->setCanClimbWalls(false);
    }

    public function canClimb(Player $player): bool
    {
        foreach ($player->getWorld()->getBlock($player->getPosition()->add(0, (count($player->getWorld()->getBlock($player->getPosition())->getCollisionBoxes()) > 0 ? ceil($player->getPosition()->y) - $player->getPosition()->y + 0.01 : 0), 0))->getHorizontalSides() as $block) {
            if ($block->isSolid()) return true;
        }
        foreach ($player->getWorld()->getBlock($player->getPosition()->add(0, 1, 0))->getHorizontalSides() as $block) {
            if ($block->isSolid()) return true;
        }
        return false;
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/VacuumEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\chestplate;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\TickingEnchantment;
use pocketmine\entity\object\ItemEntity;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;

class VacuumEnchant extends TickingEnchantment
{
    public string $name = "Vacuum";
    public int $maxLevel = 3;

    public int $usageType = CustomEnchant::TYPE_CHESTPLATE;
    public int $itemType = CustomEnchant::ITEM_TYPE_CHESTPLATE;

    public function getDefaultExtraData(): array
    {
        return ["radiusMultiplier" => 3];
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        foreach ($player->getWorld()->getEntities() as $entity) {
            if ($entity instanceof ItemEntity) {
                $distance = $player->getPosition()->distance($entity->getPosition());
                if ($distance <= $this->extraData["radiusMultiplier"] * $level) {
                    $entity->setMotion($player->getPosition()->subtractVector($entity->getPosition())->divide(3 * $level)->multiply($level));
                }
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/AntitoxinEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\helmet;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\event\entity\EntityEffectAddEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class AntitoxinEnchant extends ReactiveEnchantment
{
    public string $name = "Antitoxin";
    public int $rarity = Rarity::MYTHIC;
    public int $maxLevel = 1;

    public int $usageType = CustomEnchant::TYPE_HELMET;
    public int $itemType = CustomEnchant::ITEM_TYPE_HELMET;

    public function getReagent(): array
    {
        return [EntityEffectAddEvent::class];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityEffectAddEvent) {
            if ($event->getEffect()->getType() === VanillaEffects::POISON()) $event->cancel();
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/FocusedEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\helmet;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous\RecursiveEnchant;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\event\entity\EntityEffectAddEvent;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class FocusedEnchant extends RecursiveEnchant
{
    public string $name = "Focused";
    public int $rarity = Rarity::UNCOMMON;

    public int $usageType = CustomEnchant::TYPE_HELMET;
    public int $itemType = CustomEnchant::ITEM_TYPE_HELMET;

    public function getReagent(): array
    {
        return [EntityEffectAddEvent::class];
    }

    public function safeReact(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof EntityEffectAddEvent) {
            $effect = $event->getEffect();
            if ($effect->getType() === VanillaEffects::NAUSEA()) {
                if ($effect->getEffectLevel() - ($level * 2) > 0) {
                    $player->getEffects()->remove($effect->getType());
                    $player->getEffects()->add($effect->setAmplifier($effect->getEffectLevel() - (1 + ($level * 2))));
                }
                $event->cancel();
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/ImplantsEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\helmet;

use DaPigGuy\PiggyCustomEnchants\CustomEnchantManager;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\block\Water;
use pocketmine\event\Event;
use pocketmine\event\player\PlayerMoveEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\Item;
use pocketmine\player\Player;
use pocketmine\scheduler\ClosureTask;

class ImplantsEnchant extends ReactiveEnchantment
{
    public string $name = "Implants";

    public int $usageType = CustomEnchant::TYPE_HELMET;
    public int $itemType = CustomEnchant::ITEM_TYPE_HELMET;

    /** @var ClosureTask[] */
    public static $tasks;

    public function getReagent(): array
    {
        return [PlayerMoveEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["foodReplenishAmountMultiplier" => 1, "airTicksReplenishAmountMultiplier" => 40, "airReplenishInterval" => 60];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof PlayerMoveEvent) {
            if ($player->getHungerManager()->getFood() < 20) {
                $player->getHungerManager()->setFood($player->getHungerManager()->getFood() + $level * $this->extraData["foodReplenishAmountMultiplier"] > $player->getHungerManager()->getMaxFood() ? $player->getHungerManager()->getMaxFood() : $player->getHungerManager()->getFood() + $level * $this->extraData["foodReplenishAmountMultiplier"]);
            }
            if ($player->getAirSupplyTicks() < $player->getMaxAirSupplyTicks() && !isset(self::$tasks[$player->getName()])) {
                self::$tasks[$player->getName()] = new ClosureTask(function () use ($player): void {
                    if ($player->isOnline() && $player->isAlive() && ($enchantment = $player->getArmorInventory()->getHelmet()->getEnchantment(CustomEnchantManager::getEnchantment(CustomEnchantIds::IMPLANTS))) !== null) {
                        if (!$player->getWorld()->getBlock($player->getPosition()->add(0, 1, 0)) instanceof Water ||
                            $player->getAirSupplyTicks() >= $player->getMaxAirSupplyTicks()) {
                            self::$tasks[$player->getName()]->getHandler()->cancel();
                            unset(self::$tasks[$player->getName()]);
                            return;
                        }
                        $player->setAirSupplyTicks($player->getAirSupplyTicks() + ($enchantment->getLevel() * $this->extraData["airTicksReplenishAmountMultiplier"]) > $player->getMaxAirSupplyTicks() ? $player->getMaxAirSupplyTicks() : $player->getAirSupplyTicks() + ($enchantment->getLevel() * $this->extraData["airTicksReplenishAmountMultiplier"]));
                    } else {
                        self::$tasks[$player->getName()]->getHandler()->cancel();
                        unset(self::$tasks[$player->getName()]);
                    }
                });
                $this->plugin->getScheduler()->scheduleDelayedRepeatingTask(self::$tasks[$player->getName()], 20, $this->extraData["airReplenishInterval"]);
            }
            $this->setCooldown($player, 1);
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/MeditationEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\armor\helmet;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\TickingTrait;
use pocketmine\event\entity\EntityRegainHealthEvent;
use pocketmine\event\Event;
use pocketmine\event\player\PlayerMoveEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;

class MeditationEnchant extends ReactiveEnchantment
{
    use TickingTrait;

    public string $name = "Meditation";
    public int $rarity = Rarity::UNCOMMON;
    public int $maxLevel = 2;

    public int $usageType = CustomEnchant::TYPE_HELMET;
    public int $itemType = CustomEnchant::ITEM_TYPE_HELMET;

    /** @var Player[] */
    public array $meditating = [];
    /** @var int[] */
    public array $meditationTick;

    public function getReagent(): array
    {
        return [PlayerMoveEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["duration" => 20 * 20, "healthReplenishAmountMultiplier" => 1, "foodReplenishAmountMultiplier" => 1];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof PlayerMoveEvent) {
            $this->meditating[$player->getName()] = $player;
            $this->meditationTick[$player->getName()] = 0;
        }
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        if (isset($this->meditationTick[$player->getName()])) {
            $this->meditationTick[$player->getName()]++;
            $time = (int)($this->meditationTick[$player->getName()] / 40);
            $player->sendTip(TextFormat::DARK_GREEN . "Meditating...\n" . TextFormat::GREEN . str_repeat("▌", $time) . TextFormat::GRAY . str_repeat("▌", (20 * 20 / 40) - $time));
            if ($this->meditationTick[$player->getName()] >= $this->extraData["duration"]) {
                $this->meditationTick[$player->getName()] = 0;
                $event = new EntityRegainHealthEvent($player, $level * $this->extraData["healthReplenishAmountMultiplier"], EntityRegainHealthEvent::CAUSE_MAGIC);
                if (!$event->isCancelled()) $player->heal($event);
                $player->getHungerManager()->setFood($player->getHungerManager()->getFood() + $level * $this->extraData["foodReplenishAmountMultiplier"] > $player->getHungerManager()->getMaxFood() ? $player->getHungerManager()->getMaxFood() : $player->getHungerManager()->getFood() + $level * $this->extraData["foodReplenishAmountMultiplier"]);
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/AutoRepairEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\event\Event;
use pocketmine\event\player\PlayerMoveEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\Durable;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class AutoRepairEnchant extends ReactiveEnchantment
{
    public string $name = "Autorepair";
    public int $rarity = Rarity::UNCOMMON;

    public int $usageType = CustomEnchant::TYPE_ANY_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_DAMAGEABLE;

    public function getReagent(): array
    {
        return [PlayerMoveEvent::class];
    }

    public function getDefaultExtraData(): array
    {
        return ["baseRepair" => 1, "repairMultiplier" => 1];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if (!$item instanceof Durable || $item->getMeta() === 0) return;
        $newDir = $item->getMeta() - ((int)$this->extraData["baseRepair"] + ((int)$this->extraData["repairMultiplier"] * $level));
        if ($newDir < 0) {
            $item->setDamage(0);
        } else {
            $item->setDamage($newDir);
        }
        $inventory->setItem($slot, $item);
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/LuckyCharmEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous;

use DaPigGuy\PiggyCustomEnchants\CustomEnchantManager;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class LuckyCharmEnchant extends ToggleableEnchantment
{
    public string $name = "Lucky Charm";
    public int $rarity = Rarity::MYTHIC;
    public int $maxLevel = 3;

    public int $usageType = CustomEnchant::TYPE_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_GLOBAL;

    public function getDefaultExtraData(): array
    {
        return ["additionalMultiplier" => 0.05];
    }

    public function toggle(Player $player, Item $item, Inventory $inventory, int $slot, int $level, bool $toggle): void
    {
        /** @var ReactiveEnchantment $enchantment */
        foreach (CustomEnchantManager::getEnchantments() as $enchantment) {
            if ($enchantment->canReact()) {
                $enchantment->setChanceMultiplier($player, $enchantment->getChanceMultiplier($player) + ($toggle ? 1 : -1) * $level * $this->extraData["additionalMultiplier"]);
            }
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/RadarEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\TickingEnchantment;
use DaPigGuy\PiggyCustomEnchants\enchants\traits\ToggleTrait;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\network\mcpe\protocol\SetSpawnPositionPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\types\DimensionIds;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;
use pocketmine\world\Position;

class RadarEnchant extends TickingEnchantment
{
    use ToggleTrait;

    public string $name = "Radar";

    public int $usageType = CustomEnchant::TYPE_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_COMPASS;

    public function getDefaultExtraData(): array
    {
        return ["radiusMultiplier" => 50];
    }

    public function tick(Player $player, Item $item, Inventory $inventory, int $slot, int $level): void
    {
        $detected = $this->findNearestPlayer($player, $level * $this->extraData["radiusMultiplier"]);
        $this->setCompassPosition($player, $detected?->getPosition() ?? $player->getWorld()->getSafeSpawn());
        if ($item->equalsExact($player->getInventory()->getItemInHand())) {
            if (is_null($detected)) {
                $player->sendTip(TextFormat::RED . "No players found.");
            } else {
                $player->sendTip(TextFormat::GREEN . "Nearest player " . round($player->getPosition()->distance($detected->getPosition()), 1) . " blocks away.");
            }
        }
    }

    public function toggle(Player $player, Item $item, Inventory $inventory, int $slot, int $level, bool $toggle): void
    {
        if (!$toggle && $player->isOnline()) $this->setCompassPosition($player, $player->getWorld()->getSafeSpawn());
    }

    public function setCompassPosition(Player $player, Position $position): void
    {
        $player->getNetworkSession()->sendDataPacket(SetSpawnPositionPacket::worldSpawn(BlockPosition::fromVector3($position->floor()), DimensionIds::OVERWORLD));
    }

    public function findNearestPlayer(Player $player, int $range): ?Player
    {
        $nearestPlayer = null;
        $nearestPlayerDistance = $range;
        foreach ($player->getWorld()->getPlayers() as $p) {
            $distance = $player->getPosition()->distance($p->getPosition());
            if ($distance <= $range && $distance < $nearestPlayerDistance && $player !== $p && $p->isAlive() && !$p->isClosed() && !$p->isFlaggedForDespawn()) {
                $nearestPlayer = $p;
                $nearestPlayerDistance = $distance;
            }
        }
        return $nearestPlayer;
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/RecursiveEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous;

use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\event\Event;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;

class RecursiveEnchant extends ReactiveEnchantment
{
    /** @var bool[] */
    public static array $isUsing;

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if (isset(self::$isUsing[$player->getName()])) return;
        self::$isUsing[$player->getName()] = true;
        $this->safeReact($player, $item, $inventory, $slot, $event, $level, $stack);
        unset(self::$isUsing[$player->getName()]);
    }

    public function safeReact(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/SoulboundEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous;

use DaPigGuy\PiggyCustomEnchants\CustomEnchantManager;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchantIds;
use DaPigGuy\PiggyCustomEnchants\enchants\ReactiveEnchantment;
use pocketmine\event\Event;
use pocketmine\event\player\PlayerDeathEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\EnchantmentInstance;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;
use pocketmine\scheduler\ClosureTask;

class SoulboundEnchant extends ReactiveEnchantment
{
    public string $name = "Soulbound";
    public int $rarity = Rarity::MYTHIC;

    public int $usageType = CustomEnchant::TYPE_ANY_INVENTORY;
    public int $itemType = CustomEnchant::ITEM_TYPE_GLOBAL;

    public function getReagent(): array
    {
        return [PlayerDeathEvent::class];
    }

    public function react(Player $player, Item $item, Inventory $inventory, int $slot, Event $event, int $level, int $stack): void
    {
        if ($event instanceof PlayerDeathEvent) {
            $drops = $event->getDrops();
            foreach ($drops as $key => $drop) {
                if ($drop->equalsExact($item)) {
                    unset($drops[$key]);
                    break;
                }
            }
            $event->setDrops($drops);
            $level > 1 ? $item->addEnchantment(new EnchantmentInstance(CustomEnchantManager::getEnchantment(CustomEnchantIds::SOULBOUND), $level - 1)) : $item->removeEnchantment(CustomEnchantManager::getEnchantment(CustomEnchantIds::SOULBOUND));
            $this->plugin->getScheduler()->scheduleDelayedTask(new ClosureTask(function () use ($inventory, $slot, $item): void {
                $inventory->setItem($slot, $item);
            }), 1);
        }
    }
}

================================================
FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/ToggleableEffectEnchant.php
================================================
<?php

declare(strict_types=1);

namespace DaPigGuy\PiggyCustomEnchants\enchants\miscellaneous;

use DaPigGuy\PiggyCustomEnchants\enchants\CustomEnchant;
use DaPigGuy\PiggyCustomEnchants\enchants\ToggleableEnchantment;
use DaPigGuy\PiggyCustomEnchants\PiggyCustomEnchants;
use DaPigGuy\PiggyCustomEnchants\utils\Utils;
use pocketmine\entity\effect\Effect;
use pocketmine\entity\effect\EffectInstance;
use pocketmine\entity\effect\VanillaEffects;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\Rarity;
use pocketmine\item\Item;
use pocketmine\player\Player;

class ToggleableEffectEnchant extends ToggleableEnchantment
{
    /*
Download .txt
gitextract_jrwncx0y/

├── .gitattributes
├── .github/
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── crash.md
│   │   ├── outdated_api.md
│   │   ├── suggestion.md
│   │   └── support.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       └── main.yml
├── .gitignore
├── .poggit.yml
├── LICENSE
├── README.md
├── phpstan.neon.dist
├── plugin.yml
├── resources/
│   ├── chances.json
│   ├── config.yml
│   └── descriptions.json
└── src/
    └── DaPigGuy/
        └── PiggyCustomEnchants/
            ├── CustomEnchantManager.php
            ├── EventListener.php
            ├── PiggyCustomEnchants.php
            ├── blocks/
            │   └── PiggyObsidian.php
            ├── commands/
            │   ├── CustomEnchantsCommand.php
            │   └── subcommands/
            │       ├── AboutSubCommand.php
            │       ├── EnchantSubCommand.php
            │       ├── InfoSubCommand.php
            │       ├── ListSubCommand.php
            │       ├── NBTSubCommand.php
            │       └── RemoveSubCommand.php
            ├── enchants/
            │   ├── CustomEnchant.php
            │   ├── CustomEnchantIds.php
            │   ├── ReactiveEnchantment.php
            │   ├── TickingEnchantment.php
            │   ├── ToggleableEnchantment.php
            │   ├── armor/
            │   │   ├── AntiKnockbackEnchant.php
            │   │   ├── ArmoredEnchant.php
            │   │   ├── AttackerDeterrentEnchant.php
            │   │   ├── BerserkerEnchant.php
            │   │   ├── CactusEnchant.php
            │   │   ├── CloakingEnchant.php
            │   │   ├── EndershiftEnchant.php
            │   │   ├── EnlightedEnchant.php
            │   │   ├── ForcefieldEnchant.php
            │   │   ├── GrowEnchant.php
            │   │   ├── HeavyEnchant.php
            │   │   ├── MoltenEnchant.php
            │   │   ├── OverloadEnchant.php
            │   │   ├── PoisonousCloudEnchant.php
            │   │   ├── ReviveEnchant.php
            │   │   ├── SelfDestructEnchant.php
            │   │   ├── ShieldedEnchant.php
            │   │   ├── ShrinkEnchant.php
            │   │   ├── TankEnchant.php
            │   │   ├── boots/
            │   │   │   ├── JetpackEnchant.php
            │   │   │   ├── MagmaWalkerEnchant.php
            │   │   │   └── StompEnchantment.php
            │   │   ├── chestplate/
            │   │   │   ├── ChickenEnchant.php
            │   │   │   ├── ParachuteEnchant.php
            │   │   │   ├── ProwlEnchant.php
            │   │   │   ├── SpiderEnchant.php
            │   │   │   └── VacuumEnchant.php
            │   │   └── helmet/
            │   │       ├── AntitoxinEnchant.php
            │   │       ├── FocusedEnchant.php
            │   │       ├── ImplantsEnchant.php
            │   │       └── MeditationEnchant.php
            │   ├── miscellaneous/
            │   │   ├── AutoRepairEnchant.php
            │   │   ├── LuckyCharmEnchant.php
            │   │   ├── RadarEnchant.php
            │   │   ├── RecursiveEnchant.php
            │   │   ├── SoulboundEnchant.php
            │   │   └── ToggleableEffectEnchant.php
            │   ├── tools/
            │   │   ├── DrillerEnchant.php
            │   │   ├── EnergizingEnchant.php
            │   │   ├── ExplosiveEnchant.php
            │   │   ├── QuickeningEnchant.php
            │   │   ├── SmeltingEnchant.php
            │   │   ├── TelepathyEnchant.php
            │   │   ├── axes/
            │   │   │   └── LumberjackEnchant.php
            │   │   ├── hoe/
            │   │   │   ├── FarmerEnchant.php
            │   │   │   ├── FertilizerEnchant.php
            │   │   │   └── HarvestEnchant.php
            │   │   └── pickaxe/
            │   │       └── JackpotEnchant.php
            │   ├── traits/
            │   │   ├── ReactiveTrait.php
            │   │   ├── TickingTrait.php
            │   │   └── ToggleTrait.php
            │   └── weapons/
            │       ├── BlessedEnchant.php
            │       ├── ConditionalDamageMultiplierEnchant.php
            │       ├── DeathbringerEnchant.php
            │       ├── DeepWoundsEnchant.php
            │       ├── DisarmingEnchant.php
            │       ├── DisarmorEnchant.php
            │       ├── GooeyEnchant.php
            │       ├── HallucinationEnchant.php
            │       ├── LacedWeaponEnchant.php
            │       ├── LifestealEnchant.php
            │       ├── LightningEnchant.php
            │       ├── VampireEnchant.php
            │       └── bows/
            │           ├── AutoAimEnchant.php
            │           ├── BombardmentEnchant.php
            │           ├── BountyHunterEnchant.php
            │           ├── GrapplingEnchant.php
            │           ├── HeadhunterEnchant.php
            │           ├── HealingEnchant.php
            │           ├── MissileEnchant.php
            │           ├── MolotovEnchant.php
            │           ├── ParalyzeEnchant.php
            │           ├── PiercingEnchant.php
            │           ├── ProjectileChangingEnchant.php
            │           ├── ShuffleEnchant.php
            │           └── VolleyEnchant.php
            ├── entities/
            │   ├── BombardmentTNT.php
            │   ├── HomingArrow.php
            │   ├── PigProjectile.php
            │   ├── PiggyFireball.php
            │   ├── PiggyLightning.php
            │   ├── PiggyProjectile.php
            │   ├── PiggyTNT.php
            │   └── PiggyWitherSkull.php
            ├── particles/
            │   └── JetpackParticle.php
            ├── tasks/
            │   ├── CheckDisabledEnchantsTask.php
            │   └── TickEnchantmentsTask.php
            └── utils/
                ├── AllyChecks.php
                ├── PiggyExplosion.php
                ├── ProjectileTracker.php
                └── Utils.php
Download .txt
SYMBOL INDEX (461 symbols across 107 files)

FILE: src/DaPigGuy/PiggyCustomEnchants/CustomEnchantManager.php
  class CustomEnchantManager (line 94) | class CustomEnchantManager
    method init (line 101) | public static function init(PiggyCustomEnchants $plugin): void
    method getPlugin (line 203) | public static function getPlugin(): PiggyCustomEnchants
    method registerEnchantment (line 208) | public static function registerEnchantment(CustomEnchant $enchant): void
    method unregisterEnchantment (line 218) | public static function unregisterEnchantment(int|CustomEnchant $id): void
    method getEnchantments (line 249) | public static function getEnchantments(): array
    method getEnchantment (line 254) | public static function getEnchantment(int $id): ?CustomEnchant
    method getEnchantmentByName (line 259) | public static function getEnchantmentByName(string $name): ?CustomEnchant

FILE: src/DaPigGuy/PiggyCustomEnchants/EventListener.php
  class EventListener (line 56) | class EventListener implements Listener
    method __construct (line 58) | public function __construct(private PiggyCustomEnchants $plugin)
    method onBreak (line 65) | public function onBreak(BlockBreakEvent $event): void
    method onDataPacketReceive (line 71) | public function onDataPacketReceive(DataPacketReceiveEvent $event): void
    method onDataPacketSend (line 99) | public function onDataPacketSend(DataPacketSendEvent $event): void
    method onBlockChange (line 114) | public function onBlockChange(EntityBlockChangeEvent $event): void
    method onDamage (line 131) | public function onDamage(EntityDamageEvent $event): void
    method onEffectAdd (line 151) | public function onEffectAdd(EntityEffectAddEvent $event): void
    method onShootBow (line 160) | public function onShootBow(EntityShootBowEvent $event): void
    method onDeath (line 166) | public function onDeath(PlayerDeathEvent $event): void
    method onInteract (line 174) | public function onInteract(PlayerInteractEvent $event): void
    method onItemHold (line 182) | public function onItemHold(PlayerItemHeldEvent $event): void
    method onJoin (line 192) | public function onJoin(PlayerJoinEvent $event): void
    method onMove (line 234) | public function onMove(PlayerMoveEvent $event): void
    method onQuit (line 251) | public function onQuit(PlayerQuitEvent $event): void
    method onSneak (line 271) | public function onSneak(PlayerToggleSneakEvent $event): void
    method onProjectileHitBlock (line 279) | public function onProjectileHitBlock(ProjectileHitBlockEvent $event): ...
    method onProjectileLaunch (line 288) | public function onProjectileLaunch(ProjectileLaunchEvent $event): void
    method onTransaction (line 298) | public function onTransaction(InventoryTransactionEvent $event): void

FILE: src/DaPigGuy/PiggyCustomEnchants/PiggyCustomEnchants.php
  class PiggyCustomEnchants (line 35) | class PiggyCustomEnchants extends PluginBase
    method onEnable (line 42) | public function onEnable(): void
    method onDisable (line 112) | public function onDisable(): void
    method getEnchantmentData (line 131) | public function getEnchantmentData(string $enchant, string $data, int|...
    method setEnchantmentData (line 137) | public function setEnchantmentData(string $enchant, string $data, int|...
    method areFormsEnabled (line 148) | public function areFormsEnabled(): bool

FILE: src/DaPigGuy/PiggyCustomEnchants/blocks/PiggyObsidian.php
  class PiggyObsidian (line 13) | class PiggyObsidian extends Block
    method __construct (line 17) | public function __construct()
    method onScheduledUpdate (line 22) | public function onScheduledUpdate(): void
    method onBreak (line 31) | public function onBreak(Item $item, Player $player = null): bool
    method getDrops (line 37) | public function getDrops(Item $item): array
    method countNeighbors (line 42) | public function countNeighbors(): int
    method slightlyMelt (line 54) | public function slightlyMelt(bool $meltNeighbors): void

FILE: src/DaPigGuy/PiggyCustomEnchants/commands/CustomEnchantsCommand.php
  class CustomEnchantsCommand (line 21) | class CustomEnchantsCommand extends BaseCommand
    method onRun (line 26) | public function onRun(CommandSender $sender, string $aliasUsed, array ...
    method prepare (line 45) | public function prepare(): void

FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/AboutSubCommand.php
  class AboutSubCommand (line 14) | class AboutSubCommand extends BaseSubCommand
    method onRun (line 19) | public function onRun(CommandSender $sender, string $aliasUsed, array ...
    method prepare (line 38) | public function prepare(): void

FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/EnchantSubCommand.php
  class EnchantSubCommand (line 22) | class EnchantSubCommand extends BaseSubCommand
    method onRun (line 27) | public function onRun(CommandSender $sender, string $aliasUsed, array ...
    method onRunForm (line 79) | public function onRunForm(CommandSender $sender, string $aliasUsed, ar...
    method prepare (line 136) | public function prepare(): void

FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/InfoSubCommand.php
  class InfoSubCommand (line 20) | class InfoSubCommand extends BaseSubCommand
    method onRun (line 25) | public function onRun(CommandSender $sender, string $aliasUsed, array ...
    method showInfo (line 64) | public function showInfo(Player $player, CustomEnchant $enchantment): ...
    method prepare (line 78) | public function prepare(): void

FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/ListSubCommand.php
  class ListSubCommand (line 17) | class ListSubCommand extends BaseSubCommand
    method onRun (line 22) | public function onRun(CommandSender $sender, string $aliasUsed, array ...
    method getEnchantmentsByType (line 34) | public function getEnchantmentsByType(): array
    method getCustomEnchantList (line 49) | public function getCustomEnchantList(): string
    method sendTypesForm (line 64) | public function sendTypesForm(Player $player): void
    method sendEnchantsForm (line 85) | public function sendEnchantsForm(Player $player, int $type): void
    method prepare (line 113) | public function prepare(): void

FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/NBTSubCommand.php
  class NBTSubCommand (line 13) | class NBTSubCommand extends BaseSubCommand
    method onRun (line 18) | public function onRun(CommandSender $sender, string $aliasUsed, array ...
    method prepare (line 27) | public function prepare(): void

FILE: src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/RemoveSubCommand.php
  class RemoveSubCommand (line 18) | class RemoveSubCommand extends BaseSubCommand
    method onRun (line 23) | public function onRun(CommandSender $sender, string $aliasUsed, array ...
    method onRunForm (line 53) | public function onRunForm(CommandSender $sender, string $aliasUsed, ar...
    method prepare (line 88) | protected function prepare(): void

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/CustomEnchant.php
  class CustomEnchant (line 15) | class CustomEnchant extends Enchantment
    method __construct (line 58) | public function __construct(protected PiggyCustomEnchants $plugin, pub...
    method getId (line 77) | public function getId(): int
    method getDisplayName (line 82) | public function getDisplayName(): string
    method getDescription (line 87) | public function getDescription(): string
    method getExtraData (line 92) | public function getExtraData(): array
    method getDefaultExtraData (line 97) | public function getDefaultExtraData(): array
    method getUsageType (line 102) | public function getUsageType(): int
    method getItemType (line 107) | public function getItemType(): int
    method getPriority (line 112) | public function getPriority(): int
    method canReact (line 117) | public function canReact(): bool
    method canTick (line 122) | public function canTick(): bool
    method canToggle (line 127) | public function canToggle(): bool
    method getCooldown (line 132) | public function getCooldown(Player $player): int
    method setCooldown (line 137) | public function setCooldown(Player $player, int $cooldown): void

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/CustomEnchantIds.php
  class CustomEnchantIds (line 7) | class CustomEnchantIds

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/ReactiveEnchantment.php
  class ReactiveEnchantment (line 9) | class ReactiveEnchantment extends CustomEnchant

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/TickingEnchantment.php
  class TickingEnchantment (line 9) | class TickingEnchantment extends CustomEnchant

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/ToggleableEnchantment.php
  class ToggleableEnchantment (line 9) | class ToggleableEnchantment extends CustomEnchant

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/AntiKnockbackEnchant.php
  class AntiKnockbackEnchant (line 15) | class AntiKnockbackEnchant extends ReactiveEnchantment
    method react (line 23) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ArmoredEnchant.php
  class ArmoredEnchant (line 17) | class ArmoredEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 24) | public function getDefaultExtraData(): array
    method react (line 29) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/AttackerDeterrentEnchant.php
  class AttackerDeterrentEnchant (line 20) | class AttackerDeterrentEnchant extends ReactiveEnchantment
    method __construct (line 30) | public function __construct(PiggyCustomEnchants $plugin, int $id, stri...
    method getDefaultExtraData (line 37) | public function getDefaultExtraData(): array
    method react (line 42) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/BerserkerEnchant.php
  class BerserkerEnchant (line 17) | class BerserkerEnchant extends ReactiveEnchantment
    method getReagent (line 25) | public function getReagent(): array
    method getDefaultExtraData (line 30) | public function getDefaultExtraData(): array
    method react (line 35) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/CactusEnchant.php
  class CactusEnchant (line 17) | class CactusEnchant extends TickingEnchantment
    method getTickingInterval (line 25) | public function getTickingInterval(): int
    method tick (line 30) | public function tick(Player $player, Item $item, Inventory $inventory,...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/CloakingEnchant.php
  class CloakingEnchant (line 19) | class CloakingEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 28) | public function getDefaultExtraData(): array
    method react (line 33) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/EndershiftEnchant.php
  class EndershiftEnchant (line 17) | class EndershiftEnchant extends ReactiveEnchantment
    method getReagent (line 25) | public function getReagent(): array
    method getDefaultExtraData (line 30) | public function getDefaultExtraData(): array
    method react (line 35) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/EnlightedEnchant.php
  class EnlightedEnchant (line 18) | class EnlightedEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 26) | public function getDefaultExtraData(): array
    method react (line 31) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ForcefieldEnchant.php
  class ForcefieldEnchant (line 21) | class ForcefieldEnchant extends ToggleableEnchantment
    method getDefaultExtraData (line 31) | public function getDefaultExtraData(): array
    method tick (line 36) | public function tick(Player $player, Item $item, Inventory $inventory,...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/GrowEnchant.php
  class GrowEnchant (line 19) | class GrowEnchant extends ToggleableEnchantment
    method getReagent (line 40) | public function getReagent(): array
    method getDefaultExtraData (line 45) | public function getDefaultExtraData(): array
    method onReaction (line 50) | public function onReaction(Player $player, Item $item, Inventory $inve...
    method react (line 68) | public function react(Player $player, Item $item, Inventory $inventory...
    method tick (line 91) | public function tick(Player $player, Item $item, Inventory $inventory,...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/HeavyEnchant.php
  class HeavyEnchant (line 17) | class HeavyEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 24) | public function getDefaultExtraData(): array
    method react (line 29) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/MoltenEnchant.php
  class MoltenEnchant (line 16) | class MoltenEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 23) | public function getDefaultExtraData(): array
    method react (line 28) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/OverloadEnchant.php
  class OverloadEnchant (line 14) | class OverloadEnchant extends ToggleableEnchantment
    method getDefaultExtraData (line 23) | public function getDefaultExtraData(): array
    method toggle (line 28) | public function toggle(Player $player, Item $item, Inventory $inventor...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/PoisonousCloudEnchant.php
  class PoisonousCloudEnchant (line 19) | class PoisonousCloudEnchant extends TickingEnchantment
    method getDefaultExtraData (line 27) | public function getDefaultExtraData(): array
    method tick (line 32) | public function tick(Player $player, Item $item, Inventory $inventory,...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ReviveEnchant.php
  class ReviveEnchant (line 23) | class ReviveEnchant extends ReactiveEnchantment
    method getReagent (line 30) | public function getReagent(): array
    method getDefaultExtraData (line 35) | public function getDefaultExtraData(): array
    method react (line 40) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/SelfDestructEnchant.php
  class SelfDestructEnchant (line 18) | class SelfDestructEnchant extends ReactiveEnchantment
    method getReagent (line 25) | public function getReagent(): array
    method getDefaultExtraData (line 30) | public function getDefaultExtraData(): array
    method react (line 35) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ShieldedEnchant.php
  class ShieldedEnchant (line 15) | class ShieldedEnchant extends ToggleableEnchantment
    method toggle (line 26) | public function toggle(Player $player, Item $item, Inventory $inventor...
    method canEffectsStack (line 44) | public function canEffectsStack(): bool

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ShrinkEnchant.php
  class ShrinkEnchant (line 19) | class ShrinkEnchant extends ToggleableEnchantment
    method getReagent (line 44) | public function getReagent(): array
    method getDefaultExtraData (line 49) | public function getDefaultExtraData(): array
    method onReaction (line 54) | public function onReaction(Player $player, Item $item, Inventory $inve...
    method react (line 72) | public function react(Player $player, Item $item, Inventory $inventory...
    method tick (line 95) | public function tick(Player $player, Item $item, Inventory $inventory,...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/TankEnchant.php
  class TankEnchant (line 18) | class TankEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 26) | public function getDefaultExtraData(): array
    method react (line 31) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/boots/JetpackEnchant.php
  class JetpackEnchant (line 23) | class JetpackEnchant extends ReactiveEnchantment
    method getReagent (line 42) | public function getReagent(): array
    method getDefaultExtraData (line 47) | public function getDefaultExtraData(): array
    method react (line 52) | public function react(Player $player, Item $item, Inventory $inventory...
    method tick (line 70) | public function tick(Player $player, Item $item, Inventory $inventory,...
    method toggle (line 90) | public function toggle(Player $player, Item $item, Inventory $inventor...
    method hasActiveJetpack (line 95) | public function hasActiveJetpack(Player $player): bool
    method powerActiveJetpack (line 100) | public function powerActiveJetpack(Player $player, bool $power = true)...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/boots/MagmaWalkerEnchant.php
  class MagmaWalkerEnchant (line 19) | class MagmaWalkerEnchant extends ReactiveEnchantment
    method getReagent (line 28) | public function getReagent(): array
    method getDefaultExtraData (line 33) | public function getDefaultExtraData(): array
    method react (line 38) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/boots/StompEnchantment.php
  class StompEnchantment (line 18) | class StompEnchantment extends ReactiveEnchantment
    method getReagent (line 27) | public function getReagent(): array
    method getDefaultExtraData (line 32) | public function getDefaultExtraData(): array
    method react (line 37) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/ChickenEnchant.php
  class ChickenEnchant (line 17) | class ChickenEnchant extends TickingEnchantment
    method getDefaultExtraData (line 25) | public function getDefaultExtraData(): array
    method tick (line 30) | public function tick(Player $player, Item $item, Inventory $inventory,...
    method getTickingInterval (line 49) | public function getTickingInterval(): int

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/ParachuteEnchant.php
  class ParachuteEnchant (line 21) | class ParachuteEnchant extends TickingEnchantment
    method tick (line 32) | public function tick(Player $player, Item $item, Inventory $inventory,...
    method toggle (line 42) | public function toggle(Player $player, Item $item, Inventory $inventor...
    method isInAir (line 49) | public function isInAir(Player $player): bool

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/ProwlEnchant.php
  class ProwlEnchant (line 16) | class ProwlEnchant extends ToggleableEnchantment
    method toggle (line 29) | public function toggle(Player $player, Item $item, Inventory $inventor...
    method tick (line 43) | public function tick(Player $player, Item $item, Inventory $inventory,...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/SpiderEnchant.php
  class SpiderEnchant (line 14) | class SpiderEnchant extends ToggleableEnchantment
    method tick (line 25) | public function tick(Player $player, Item $item, Inventory $inventory,...
    method toggle (line 30) | public function toggle(Player $player, Item $item, Inventory $inventor...
    method canClimb (line 35) | public function canClimb(Player $player): bool

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/VacuumEnchant.php
  class VacuumEnchant (line 14) | class VacuumEnchant extends TickingEnchantment
    method getDefaultExtraData (line 22) | public function getDefaultExtraData(): array
    method tick (line 27) | public function tick(Player $player, Item $item, Inventory $inventory,...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/AntitoxinEnchant.php
  class AntitoxinEnchant (line 17) | class AntitoxinEnchant extends ReactiveEnchantment
    method getReagent (line 26) | public function getReagent(): array
    method react (line 31) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/FocusedEnchant.php
  class FocusedEnchant (line 17) | class FocusedEnchant extends RecursiveEnchant
    method getReagent (line 25) | public function getReagent(): array
    method safeReact (line 30) | public function safeReact(Player $player, Item $item, Inventory $inven...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/ImplantsEnchant.php
  class ImplantsEnchant (line 20) | class ImplantsEnchant extends ReactiveEnchantment
    method getReagent (line 30) | public function getReagent(): array
    method getDefaultExtraData (line 35) | public function getDefaultExtraData(): array
    method react (line 40) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/MeditationEnchant.php
  class MeditationEnchant (line 19) | class MeditationEnchant extends ReactiveEnchantment
    method getReagent (line 35) | public function getReagent(): array
    method getDefaultExtraData (line 40) | public function getDefaultExtraData(): array
    method react (line 45) | public function react(Player $player, Item $item, Inventory $inventory...
    method tick (line 53) | public function tick(Player $player, Item $item, Inventory $inventory,...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/AutoRepairEnchant.php
  class AutoRepairEnchant (line 17) | class AutoRepairEnchant extends ReactiveEnchantment
    method getReagent (line 25) | public function getReagent(): array
    method getDefaultExtraData (line 30) | public function getDefaultExtraData(): array
    method react (line 35) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/LuckyCharmEnchant.php
  class LuckyCharmEnchant (line 16) | class LuckyCharmEnchant extends ToggleableEnchantment
    method getDefaultExtraData (line 25) | public function getDefaultExtraData(): array
    method toggle (line 30) | public function toggle(Player $player, Item $item, Inventory $inventor...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/RadarEnchant.php
  class RadarEnchant (line 19) | class RadarEnchant extends TickingEnchantment
    method getDefaultExtraData (line 28) | public function getDefaultExtraData(): array
    method tick (line 33) | public function tick(Player $player, Item $item, Inventory $inventory,...
    method toggle (line 46) | public function toggle(Player $player, Item $item, Inventory $inventor...
    method setCompassPosition (line 51) | public function setCompassPosition(Player $player, Position $position)...
    method findNearestPlayer (line 56) | public function findNearestPlayer(Player $player, int $range): ?Player

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/RecursiveEnchant.php
  class RecursiveEnchant (line 13) | class RecursiveEnchant extends ReactiveEnchantment
    method react (line 18) | public function react(Player $player, Item $item, Inventory $inventory...
    method safeReact (line 26) | public function safeReact(Player $player, Item $item, Inventory $inven...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/SoulboundEnchant.php
  class SoulboundEnchant (line 20) | class SoulboundEnchant extends ReactiveEnchantment
    method getReagent (line 28) | public function getReagent(): array
    method react (line 33) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/ToggleableEffectEnchant.php
  class ToggleableEffectEnchant (line 19) | class ToggleableEffectEnchant extends ToggleableEnchantment
    method __construct (line 24) | public function __construct(PiggyCustomEnchants $plugin, int $id, stri...
    method getDefaultExtraData (line 34) | public function getDefaultExtraData(): array
    method toggle (line 39) | public function toggle(Player $player, Item $item, Inventory $inventor...
    method getUsageType (line 61) | public function getUsageType(): int
    method getItemType (line 66) | public function getItemType(): int

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/DrillerEnchant.php
  class DrillerEnchant (line 18) | class DrillerEnchant extends RecursiveEnchant
    method getReagent (line 28) | public function getReagent(): array
    method getDefaultExtraData (line 33) | public function getDefaultExtraData(): array
    method safeReact (line 38) | public function safeReact(Player $player, Item $item, Inventory $inven...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/EnergizingEnchant.php
  class EnergizingEnchant (line 17) | class EnergizingEnchant extends ReactiveEnchantment
    method getReagent (line 23) | public function getReagent(): array
    method getDefaultExtraData (line 28) | public function getDefaultExtraData(): array
    method react (line 33) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/ExplosiveEnchant.php
  class ExplosiveEnchant (line 17) | class ExplosiveEnchant extends RecursiveEnchant
    method getReagent (line 24) | public function getReagent(): array
    method getDefaultExtraData (line 29) | public function getDefaultExtraData(): array
    method safeReact (line 34) | public function safeReact(Player $player, Item $item, Inventory $inven...
    method getPriority (line 43) | public function getPriority(): int

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/QuickeningEnchant.php
  class QuickeningEnchant (line 18) | class QuickeningEnchant extends ReactiveEnchantment
    method getReagent (line 25) | public function getReagent(): array
    method getDefaultExtraData (line 30) | public function getDefaultExtraData(): array
    method react (line 35) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/SmeltingEnchant.php
  class SmeltingEnchant (line 17) | class SmeltingEnchant extends ReactiveEnchantment
    method getReagent (line 25) | public function getReagent(): array
    method react (line 30) | public function react(Player $player, Item $item, Inventory $inventory...
    method getPriority (line 37) | public function getPriority(): int

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/TelepathyEnchant.php
  class TelepathyEnchant (line 15) | class TelepathyEnchant extends ReactiveEnchantment
    method getReagent (line 22) | public function getReagent(): array
    method react (line 27) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/axes/LumberjackEnchant.php
  class LumberjackEnchant (line 17) | class LumberjackEnchant extends RecursiveEnchant
    method getReagent (line 24) | public function getReagent(): array
    method getDefaultExtraData (line 29) | public function getDefaultExtraData(): array
    method safeReact (line 34) | public function safeReact(Player $player, Item $item, Inventory $inven...
    method breakTree (line 46) | public function breakTree(Block $block, Player $player, int $mined = 0...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/hoe/FarmerEnchant.php
  class FarmerEnchant (line 19) | class FarmerEnchant extends ReactiveEnchantment
    method getReagent (line 27) | public function getReagent(): array
    method react (line 32) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/hoe/FertilizerEnchant.php
  class FertilizerEnchant (line 18) | class FertilizerEnchant extends RecursiveEnchant
    method getReagent (line 26) | public function getReagent(): array
    method getDefaultExtraData (line 31) | public function getDefaultExtraData(): array
    method safeReact (line 36) | public function safeReact(Player $player, Item $item, Inventory $inven...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/hoe/HarvestEnchant.php
  class HarvestEnchant (line 17) | class HarvestEnchant extends RecursiveEnchant
    method getReagent (line 25) | public function getReagent(): array
    method getDefaultExtraData (line 30) | public function getDefaultExtraData(): array
    method safeReact (line 35) | public function safeReact(Player $player, Item $item, Inventory $inven...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/tools/pickaxe/JackpotEnchant.php
  class JackpotEnchant (line 19) | class JackpotEnchant extends ReactiveEnchantment
    method getReagent (line 34) | public function getReagent(): array
    method react (line 39) | public function react(Player $player, Item $item, Inventory $inventory...
    method getPriority (line 58) | public function getPriority(): int

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/traits/ReactiveTrait.php
  type ReactiveTrait (line 21) | trait ReactiveTrait
    method canReact (line 28) | public function canReact(): bool
    method getReagent (line 33) | public function getReagent(): array
    method onReaction (line 38) | public function onReaction(Player $player, Item $item, Inventory $inve...
    method react (line 54) | public function react(Player $player, Item $item, Inventory $inventory...
    method getChance (line 58) | public function getChance(Player $player, int $level): float
    method getBaseChance (line 65) | public function getBaseChance(int $level): float
    method getChanceMultiplier (line 70) | public function getChanceMultiplier(Player $player): float
    method setChanceMultiplier (line 75) | public function setChanceMultiplier(Player $player, float $multiplier)...
    method getCooldownDuration (line 80) | public function getCooldownDuration(): int
    method shouldReactToDamage (line 85) | public function shouldReactToDamage(): bool
    method shouldReactToDamaged (line 90) | public function shouldReactToDamaged(): bool
    method attemptReaction (line 95) | public static function attemptReaction(Player $player, Event $event): ...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/traits/TickingTrait.php
  type TickingTrait (line 12) | trait TickingTrait
    method canTick (line 16) | public function canTick(): bool
    method getTickingInterval (line 21) | public function getTickingInterval(): int
    method onTick (line 26) | public function onTick(Player $player, Item $item, Inventory $inventor...
    method tick (line 34) | public function tick(Player $player, Item $item, Inventory $inventory,...
    method supportsMultipleItems (line 39) | public function supportsMultipleItems(): bool

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/traits/ToggleTrait.php
  type ToggleTrait (line 18) | trait ToggleTrait
    method canToggle (line 27) | public function canToggle(): bool
    method onToggle (line 32) | public function onToggle(Player $player, Item $item, Inventory $invent...
    method toggle (line 41) | public function toggle(Player $player, Item $item, Inventory $inventor...
    method addToStack (line 45) | public function addToStack(Player $player, int $level): void
    method removeFromStack (line 51) | public function removeFromStack(Player $player, int $level): void
    method getStack (line 57) | public function getStack(Player $player): int
    method getArmorStack (line 63) | public function getArmorStack(Player $player): int
    method attemptToggle (line 69) | public static function attemptToggle(Player $player, Item $item, Encha...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/BlessedEnchant.php
  class BlessedEnchant (line 15) | class BlessedEnchant extends ReactiveEnchantment
    method react (line 21) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/ConditionalDamageMultiplierEnchant.php
  class ConditionalDamageMultiplierEnchant (line 16) | class ConditionalDamageMultiplierEnchant extends ReactiveEnchantment
    method __construct (line 21) | public function __construct(PiggyCustomEnchants $plugin, int $id, stri...
    method getDefaultExtraData (line 28) | public function getDefaultExtraData(): array
    method react (line 33) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/DeathbringerEnchant.php
  class DeathbringerEnchant (line 15) | class DeathbringerEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 19) | public function getDefaultExtraData(): array
    method react (line 24) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/DeepWoundsEnchant.php
  class DeepWoundsEnchant (line 18) | class DeepWoundsEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 26) | public function getDefaultExtraData(): array
    method react (line 31) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/DisarmingEnchant.php
  class DisarmingEnchant (line 15) | class DisarmingEnchant extends ReactiveEnchantment
    method react (line 20) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/DisarmorEnchant.php
  class DisarmorEnchant (line 14) | class DisarmorEnchant extends DisarmingEnchant
    method react (line 19) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/GooeyEnchant.php
  class GooeyEnchant (line 16) | class GooeyEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 20) | public function getDefaultExtraData(): array
    method react (line 25) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/HallucinationEnchant.php
  class HallucinationEnchant (line 30) | class HallucinationEnchant extends ReactiveEnchantment
    method react (line 41) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/LacedWeaponEnchant.php
  class LacedWeaponEnchant (line 20) | class LacedWeaponEnchant extends ReactiveEnchantment
    method __construct (line 29) | public function __construct(PiggyCustomEnchants $plugin, int $id, stri...
    method getDefaultExtraData (line 37) | public function getDefaultExtraData(): array
    method react (line 42) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/LifestealEnchant.php
  class LifestealEnchant (line 15) | class LifestealEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 20) | public function getDefaultExtraData(): array
    method react (line 25) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/LightningEnchant.php
  class LightningEnchant (line 16) | class LightningEnchant extends ReactiveEnchantment
    method react (line 21) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/VampireEnchant.php
  class VampireEnchant (line 15) | class VampireEnchant extends ReactiveEnchantment
    method getDefaultExtraData (line 22) | public function getDefaultExtraData(): array
    method react (line 27) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/AutoAimEnchant.php
  class AutoAimEnchant (line 17) | class AutoAimEnchant extends TickingEnchantment
    method getDefaultExtraData (line 25) | public function getDefaultExtraData(): array
    method tick (line 30) | public function tick(Player $player, Item $item, Inventory $inventory,...
    method findNearestEntity (line 48) | public function findNearestEntity(Player $player, int $range): ?Living

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/BombardmentEnchant.php
  class BombardmentEnchant (line 18) | class BombardmentEnchant extends ReactiveEnchantment
    method getReagent (line 24) | public function getReagent(): array
    method react (line 29) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/BountyHunterEnchant.php
  class BountyHunterEnchant (line 18) | class BountyHunterEnchant extends ReactiveEnchantment
    method getReagent (line 26) | public function getReagent(): array
    method getDefaultExtraData (line 31) | public function getDefaultExtraData(): array
    method react (line 36) | public function react(Player $player, Item $item, Inventory $inventory...
    method getBounty (line 44) | public function getBounty(): int

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/GrapplingEnchant.php
  class GrapplingEnchant (line 20) | class GrapplingEnchant extends ReactiveEnchantment
    method getReagent (line 27) | public function getReagent(): array
    method react (line 32) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/HeadhunterEnchant.php
  class HeadhunterEnchant (line 17) | class HeadhunterEnchant extends ReactiveEnchantment
    method getReagent (line 24) | public function getReagent(): array
    method getDefaultExtraData (line 29) | public function getDefaultExtraData(): array
    method react (line 34) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/HealingEnchant.php
  class HealingEnchant (line 15) | class HealingEnchant extends ReactiveEnchantment
    method getReagent (line 21) | public function getReagent(): array
    method getDefaultExtraData (line 26) | public function getDefaultExtraData(): array
    method react (line 31) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/MissileEnchant.php
  class MissileEnchant (line 16) | class MissileEnchant extends ReactiveEnchantment
    method getReagent (line 22) | public function getReagent(): array
    method getDefaultExtraData (line 27) | public function getDefaultExtraData(): array
    method react (line 32) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/MolotovEnchant.php
  class MolotovEnchant (line 20) | class MolotovEnchant extends ReactiveEnchantment
    method getReagent (line 27) | public function getReagent(): array
    method react (line 32) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/ParalyzeEnchant.php
  class ParalyzeEnchant (line 18) | class ParalyzeEnchant extends ReactiveEnchantment
    method getReagent (line 24) | public function getReagent(): array
    method getDefaultExtraData (line 29) | public function getDefaultExtraData(): array
    method react (line 45) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/PiercingEnchant.php
  class PiercingEnchant (line 16) | class PiercingEnchant extends ReactiveEnchantment
    method getReagent (line 23) | public function getReagent(): array
    method react (line 28) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/ProjectileChangingEnchant.php
  class ProjectileChangingEnchant (line 21) | class ProjectileChangingEnchant extends ReactiveEnchantment
    method __construct (line 28) | public function __construct(PiggyCustomEnchants $plugin, int $id, stri...
    method getReagent (line 36) | public function getReagent(): array
    method react (line 41) | public function react(Player $player, Item $item, Inventory $inventory...
    method getPriority (line 57) | public function getPriority(): int

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/ShuffleEnchant.php
  class ShuffleEnchant (line 17) | class ShuffleEnchant extends ReactiveEnchantment
    method getReagent (line 24) | public function getReagent(): array
    method react (line 29) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/VolleyEnchant.php
  class VolleyEnchant (line 22) | class VolleyEnchant extends ReactiveEnchantment
    method getReagent (line 29) | public function getReagent(): array
    method getDefaultExtraData (line 34) | public function getDefaultExtraData(): array
    method react (line 39) | public function react(Player $player, Item $item, Inventory $inventory...

FILE: src/DaPigGuy/PiggyCustomEnchants/entities/BombardmentTNT.php
  class BombardmentTNT (line 12) | class BombardmentTNT extends FallingBlock
    method __construct (line 16) | public function __construct(Location $location, ?CompoundTag $nbt = nu...
    method getEnchantmentLevel (line 22) | public function getEnchantmentLevel(): int
    method saveNBT (line 27) | public function saveNBT(): CompoundTag

FILE: src/DaPigGuy/PiggyCustomEnchants/entities/HomingArrow.php
  class HomingArrow (line 16) | class HomingArrow extends Arrow
    method __construct (line 20) | public function __construct(Location $location, ?Entity $shootingEntit...
    method entityBaseTick (line 26) | public function entityBaseTick(int $tickDiff = 1): bool
    method getEnchantmentLevel (line 38) | public function getEnchantmentLevel(): int
    method findNearestEntity (line 43) | public function findNearestEntity(int $range): ?Living
    method lookAt (line 59) | public function lookAt(Vector3 $target): void

FILE: src/DaPigGuy/PiggyCustomEnchants/entities/PigProjectile.php
  class PigProjectile (line 24) | class PigProjectile extends PiggyProjectile
    method __construct (line 49) | public function __construct(Location $location, ?Entity $shootingEntit...
    method entityBaseTick (line 61) | public function entityBaseTick(int $tickDiff = 1): bool
    method getPorkLevel (line 83) | public function getPorkLevel(): int
    method isZombie (line 88) | public function isZombie(): bool
    method getDrops (line 96) | public function getDrops(): array
    method sendSpawnPacket (line 104) | protected function sendSpawnPacket(Player $player): void
    method getNetworkTypeId (line 125) | public static function getNetworkTypeId(): string
    method getInitialSizeInfo (line 130) | protected function getInitialSizeInfo(): EntitySizeInfo

FILE: src/DaPigGuy/PiggyCustomEnchants/entities/PiggyFireball.php
  class PiggyFireball (line 17) | class PiggyFireball extends PiggyProjectile
    method onHitEntity (line 27) | public function onHitEntity(Entity $entityHit, RayTraceResult $hitResu...
    method onHitBlock (line 38) | public function onHitBlock(Block $blockHit, RayTraceResult $hitResult)...
    method getNetworkTypeId (line 44) | public static function getNetworkTypeId(): string
    method getInitialSizeInfo (line 49) | protected function getInitialSizeInfo(): EntitySizeInfo

FILE: src/DaPigGuy/PiggyCustomEnchants/entities/PiggyLightning.php
  class PiggyLightning (line 19) | class PiggyLightning extends Entity
    method entityBaseTick (line 23) | public function entityBaseTick(int $tickDiff = 1): bool
    method getNetworkTypeId (line 48) | public static function getNetworkTypeId(): string
    method getInitialSizeInfo (line 53) | protected function getInitialSizeInfo(): EntitySizeInfo

FILE: src/DaPigGuy/PiggyCustomEnchants/entities/PiggyProjectile.php
  class PiggyProjectile (line 8) | abstract class PiggyProjectile extends Projectile
    method onHit (line 10) | public function onHit(ProjectileHitEvent $event): void
    method canSaveWithChunk (line 16) | public function canSaveWithChunk(): bool

FILE: src/DaPigGuy/PiggyCustomEnchants/entities/PiggyTNT.php
  class PiggyTNT (line 15) | class PiggyTNT extends PrimedTNT
    method __construct (line 19) | public function __construct(Location $location, ?CompoundTag $nbt = nu...
    method explode (line 25) | public function explode(): void

FILE: src/DaPigGuy/PiggyCustomEnchants/entities/PiggyWitherSkull.php
  class PiggyWitherSkull (line 17) | class PiggyWitherSkull extends PiggyProjectile
    method onHitEntity (line 27) | public function onHitEntity(Entity $entityHit, RayTraceResult $hitResu...
    method getNetworkTypeId (line 39) | public static function getNetworkTypeId(): string
    method getInitialSizeInfo (line 44) | protected function getInitialSizeInfo(): EntitySizeInfo

FILE: src/DaPigGuy/PiggyCustomEnchants/particles/JetpackParticle.php
  class JetpackParticle (line 12) | class JetpackParticle implements Particle
    method encode (line 14) | public function encode(Vector3 $pos): array

FILE: src/DaPigGuy/PiggyCustomEnchants/tasks/CheckDisabledEnchantsTask.php
  class CheckDisabledEnchantsTask (line 11) | class CheckDisabledEnchantsTask extends AsyncTask
    method onRun (line 13) | public function onRun(): void
    method onCompletion (line 20) | public function onCompletion(): void

FILE: src/DaPigGuy/PiggyCustomEnchants/tasks/TickEnchantmentsTask.php
  class TickEnchantmentsTask (line 18) | class TickEnchantmentsTask extends Task
    method __construct (line 20) | public function __construct(private PiggyCustomEnchants $plugin)
    method onRun (line 24) | public function onRun(): void
    method cleanOldItems (line 86) | public function cleanOldItems(Item $item): Item

FILE: src/DaPigGuy/PiggyCustomEnchants/utils/AllyChecks.php
  class AllyChecks (line 12) | class AllyChecks
    method addCheck (line 22) | public static function addCheck(Plugin $plugin, callable $check): void
    method isAlly (line 30) | public static function isAlly(Player $player, Entity $entity): bool

FILE: src/DaPigGuy/PiggyCustomEnchants/utils/PiggyExplosion.php
  class PiggyExplosion (line 22) | class PiggyExplosion extends Explosion
    method __construct (line 24) | public function __construct(Position $center, float $size, protected P...
    method explodeB (line 29) | public function explodeB(): bool

FILE: src/DaPigGuy/PiggyCustomEnchants/utils/ProjectileTracker.php
  class ProjectileTracker (line 11) | class ProjectileTracker
    method addProjectile (line 16) | public static function addProjectile(Projectile $projectile, Item $ite...
    method isTrackedProjectile (line 21) | public static function isTrackedProjectile(Projectile $projectile): bool
    method getItem (line 26) | public static function getItem(Projectile $projectile): ?Item
    method getEnchantments (line 35) | public static function getEnchantments(Projectile $projectile): array
    method removeProjectile (line 42) | public static function removeProjectile(Projectile $projectile): void

FILE: src/DaPigGuy/PiggyCustomEnchants/utils/Utils.php
  class Utils (line 41) | class Utils
    method getRomanNumeral (line 80) | public static function getRomanNumeral(int $integer): string
    method isHelmet (line 110) | public static function isHelmet(Item $item): bool
    method isChestplate (line 115) | public static function isChestplate(Item $item): bool
    method isLeggings (line 120) | public static function isLeggings(Item $item): bool
    method isBoots (line 125) | public static function isBoots(Item $item): bool
    method itemMatchesItemType (line 130) | public static function itemMatchesItemType(Item $item, int $itemType):...
    method createNewProjectile (line 154) | public static function createNewProjectile(string $className, Location...
    method checkEnchantIncompatibilities (line 165) | public static function checkEnchantIncompatibilities(Item $item, Custo...
    method displayEnchants (line 176) | public static function displayEnchants(ItemStack $itemStack): ItemStack
    method filterDisplayedEnchants (line 201) | public static function filterDisplayedEnchants(ItemStack $itemStack): ...
    method sortEnchantmentsByPriority (line 218) | public static function sortEnchantmentsByPriority(array $enchantments)...
    method getColorFromRarity (line 228) | public static function getColorFromRarity(int $rarity): string
    method getTFConstFromString (line 233) | public static function getTFConstFromString(string $color): string
    method errorForm (line 256) | public static function errorForm(Player $player, string $error): void
    method shouldTakeFallDamage (line 265) | public static function shouldTakeFallDamage(Player $player): bool
    method setShouldTakeFallDamage (line 270) | public static function setShouldTakeFallDamage(Player $player, bool $s...
    method getNoFallDamageDuration (line 276) | public static function getNoFallDamageDuration(Player $player): int
    method increaseNoFallDamageDuration (line 281) | public static function increaseNoFallDamageDuration(Player $player, in...
    method isCoolKid (line 286) | public static function isCoolKid(PluginDescription $description): bool
Condensed preview — 125 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (336K chars).
[
  {
    "path": ".gitattributes",
    "chars": 378,
    "preview": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Custom for Visual Studio\n*.cs     diff=csharp\n\n# St"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 675,
    "preview": "# PiggyCustomEnchants\n\n## Contribution Guidelines\n\n### Issues\nIf you are submitting an issue ticket, you must:\n* Must be"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 969,
    "preview": "---\nname: Bug Report\nabout: Unexpected non-crash behavior with PiggyCustomEnchants\ntitle: ''\nlabels: 'Type: Bug'\nassigne"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/crash.md",
    "chars": 717,
    "preview": "---\nname: Crash\nabout: Report a crash in PiggyCustomEnchants\ntitle: ''\nlabels: 'Type: Bug'\nassignees: 'DaPigGuy'\n---\n\n<!"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/outdated_api.md",
    "chars": 298,
    "preview": "---\nname: Outdated API Version\nabout: Please do not create an issue for this. The plugin will be updated to the latest P"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/suggestion.md",
    "chars": 517,
    "preview": "---\nname: Feature Suggestion\nabout: Suggest features you would like added to PiggyCustomEnchants\ntitle: ''\nlabels: 'Type"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/support.md",
    "chars": 257,
    "preview": "---\nname: Support\nabout: Please do not create an issue for this. Join our Discord for support (link in README).\ntitle: '"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 759,
    "preview": "<!-- Failure to complete the required fields will result in the issue being closed. -->\nPlease make sure your pull reque"
  },
  {
    "path": ".github/workflows/main.yml",
    "chars": 769,
    "preview": "name: PHPStan\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n\njobs:\n  phpstan:\n    runs-on: ubuntu-latest\n   "
  },
  {
    "path": ".gitignore",
    "chars": 249,
    "preview": "# Windows image file caches\nThumbs.db\nehthumbs.db\n\n# Folder config file\nDesktop.ini\n\n# Recycle Bin used on file shares\n$"
  },
  {
    "path": ".poggit.yml",
    "chars": 463,
    "preview": "--- # Poggit-CI Manifest. Open the CI at https://poggit.pmmp.io/ci/DaPigGuy/PiggyCustomEnchants\nbranches:\n  - master\n  -"
  },
  {
    "path": "LICENSE",
    "chars": 11338,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 7645,
    "preview": "# PiggyCustomEnchants [![Poggit-CI](https://poggit.pmmp.io/shield.dl/PiggyCustomEnchants)](https://poggit.pmmp.io/p/Pigg"
  },
  {
    "path": "phpstan.neon.dist",
    "chars": 541,
    "preview": "parameters:\n  paths:\n    - /source/src\n  level: 7\n  bootstrapFiles:\n    - phar:///pocketmine/PocketMine-MP.phar/vendor/a"
  },
  {
    "path": "plugin.yml",
    "chars": 1581,
    "preview": "name: PiggyCustomEnchants\nmain: DaPigGuy\\PiggyCustomEnchants\\PiggyCustomEnchants\nversion: 3.0.12\napi: 4.21.0\nload: POSTW"
  },
  {
    "path": "resources/chances.json",
    "chars": 134,
    "preview": "{\n  \"blessed\": 15,\n  \"deepwounds\": 20,\n  \"disarmor\": 10,\n  \"disarming\": 10,\n  \"hallucination\": 5,\n  \"jackpot\": 10,\n  \"li"
  },
  {
    "path": "resources/config.yml",
    "chars": 1368,
    "preview": "# Specifies the color enchants are shown depending on rarity\n# Options: black, dark_blue, dark_green, dark_aqua, dark_re"
  },
  {
    "path": "resources/descriptions.json",
    "chars": 5286,
    "preview": "{\n  \"antiknockback\": \"Reduces knockback per armor piece.\",\n  \"antitoxin\": \"Grants immunity to poison.\",\n  \"aerial\": \"Whi"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/CustomEnchantManager.php",
    "chars": 19777,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants;\n\nuse DaPigGuy\\PiggyCustomEnchants\\enchants\\armo"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/EventListener.php",
    "chars": 15840,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants;\n\nuse DaPigGuy\\PiggyCustomEnchants\\enchants\\Cust"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/PiggyCustomEnchants.php",
    "chars": 7279,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants;\n\nuse CortexPE\\Commando\\BaseCommand;\nuse CortexP"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/blocks/PiggyObsidian.php",
    "chars": 1999,
    "preview": "<?php\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\blocks;\n\nuse pocketmine\\block\\Block;\nuse pocketmine\\block\\BlockBreakInfo;\n"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/commands/CustomEnchantsCommand.php",
    "chars": 2619,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\commands;\n\nuse CortexPE\\Commando\\BaseCommand;\nus"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/AboutSubCommand.php",
    "chars": 1762,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\commands\\subcommands;\n\nuse CortexPE\\Commando\\Bas"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/EnchantSubCommand.php",
    "chars": 7076,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\commands\\subcommands;\n\nuse CortexPE\\Commando\\arg"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/InfoSubCommand.php",
    "chars": 3956,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\commands\\subcommands;\n\nuse CortexPE\\Commando\\arg"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/ListSubCommand.php",
    "chars": 5140,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\commands\\subcommands;\n\nuse CortexPE\\Commando\\Bas"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/NBTSubCommand.php",
    "chars": 861,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\commands\\subcommands;\n\nuse CortexPE\\Commando\\Bas"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/commands/subcommands/RemoveSubCommand.php",
    "chars": 4077,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\commands\\subcommands;\n\nuse CortexPE\\Commando\\arg"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/CustomEnchant.php",
    "chars": 4264,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants;\n\nuse DaPigGuy\\PiggyCustomEnchants\\Pigg"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/CustomEnchantIds.php",
    "chars": 3047,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants;\n\nclass CustomEnchantIds\n{\n    /**\n    "
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/ReactiveEnchantment.php",
    "chars": 222,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants;\n\nuse DaPigGuy\\PiggyCustomEnchants\\ench"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/TickingEnchantment.php",
    "chars": 219,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants;\n\nuse DaPigGuy\\PiggyCustomEnchants\\ench"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/ToggleableEnchantment.php",
    "chars": 220,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants;\n\nuse DaPigGuy\\PiggyCustomEnchants\\ench"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/AntiKnockbackEnchant.php",
    "chars": 989,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ArmoredEnchant.php",
    "chars": 1371,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/AttackerDeterrentEnchant.php",
    "chars": 2005,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/BerserkerEnchant.php",
    "chars": 1811,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/CactusEnchant.php",
    "chars": 1305,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/CloakingEnchant.php",
    "chars": 1405,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/EndershiftEnchant.php",
    "chars": 2266,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/EnlightedEnchant.php",
    "chars": 1380,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ForcefieldEnchant.php",
    "chars": 2567,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/GrowEnchant.php",
    "chars": 4406,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/HeavyEnchant.php",
    "chars": 1376,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/MoltenEnchant.php",
    "chars": 1178,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/OverloadEnchant.php",
    "chars": 1152,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/PoisonousCloudEnchant.php",
    "chars": 2309,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ReviveEnchant.php",
    "chars": 2923,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/SelfDestructEnchant.php",
    "chars": 1659,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ShieldedEnchant.php",
    "chars": 1880,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/ShrinkEnchant.php",
    "chars": 4505,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/TankEnchant.php",
    "chars": 1441,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/boots/JetpackEnchant.php",
    "chars": 5808,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\boots;\n\nuse DaPigGuy\\PiggyCustomE"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/boots/MagmaWalkerEnchant.php",
    "chars": 2123,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\boots;\n\nuse DaPigGuy\\PiggyCustomE"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/boots/StompEnchantment.php",
    "chars": 2014,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\boots;\n\nuse DaPigGuy\\PiggyCustomE"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/ChickenEnchant.php",
    "chars": 2181,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\chestplate;\n\nuse DaPigGuy\\PiggyCu"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/ParachuteEnchant.php",
    "chars": 2628,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\chestplate;\n\nuse DaPigGuy\\PiggyCu"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/ProwlEnchant.php",
    "chars": 2425,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\chestplate;\n\nuse DaPigGuy\\PiggyCu"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/SpiderEnchant.php",
    "chars": 1614,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\chestplate;\n\nuse DaPigGuy\\PiggyCu"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/chestplate/VacuumEnchant.php",
    "chars": 1282,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\chestplate;\n\nuse DaPigGuy\\PiggyCu"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/AntitoxinEnchant.php",
    "chars": 1155,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\helmet;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/FocusedEnchant.php",
    "chars": 1474,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\helmet;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/ImplantsEnchant.php",
    "chars": 3444,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\helmet;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/armor/helmet/MeditationEnchant.php",
    "chars": 2841,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\armor\\helmet;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/AutoRepairEnchant.php",
    "chars": 1452,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\miscellaneous;\n\nuse DaPigGuy\\PiggyCusto"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/LuckyCharmEnchant.php",
    "chars": 1377,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\miscellaneous;\n\nuse DaPigGuy\\PiggyCusto"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/RadarEnchant.php",
    "chars": 2776,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\miscellaneous;\n\nuse DaPigGuy\\PiggyCusto"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/RecursiveEnchant.php",
    "chars": 934,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\miscellaneous;\n\nuse DaPigGuy\\PiggyCusto"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/SoulboundEnchant.php",
    "chars": 1910,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\miscellaneous;\n\nuse DaPigGuy\\PiggyCusto"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/miscellaneous/ToggleableEffectEnchant.php",
    "chars": 3004,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\miscellaneous;\n\nuse DaPigGuy\\PiggyCusto"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/DrillerEnchant.php",
    "chars": 2759,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/EnergizingEnchant.php",
    "chars": 1397,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/ExplosiveEnchant.php",
    "chars": 1410,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/QuickeningEnchant.php",
    "chars": 1487,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/SmeltingEnchant.php",
    "chars": 1257,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/TelepathyEnchant.php",
    "chars": 1834,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools;\n\nuse DaPigGuy\\PiggyCustomEnchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/axes/LumberjackEnchant.php",
    "chars": 1938,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools\\axes;\n\nuse DaPigGuy\\PiggyCustomEn"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/hoe/FarmerEnchant.php",
    "chars": 1683,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools\\hoe;\n\nuse DaPigGuy\\PiggyCustomEnc"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/hoe/FertilizerEnchant.php",
    "chars": 2014,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools\\hoe;\n\nuse DaPigGuy\\PiggyCustomEnc"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/hoe/HarvestEnchant.php",
    "chars": 1699,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools\\hoe;\n\nuse DaPigGuy\\PiggyCustomEnc"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/tools/pickaxe/JackpotEnchant.php",
    "chars": 1993,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\tools\\pickaxe;\n\nuse DaPigGuy\\PiggyCusto"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/traits/ReactiveTrait.php",
    "chars": 8468,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\traits;\n\nuse DaPigGuy\\PiggyCustomEnchan"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/traits/TickingTrait.php",
    "chars": 1182,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\traits;\n\nuse DaPigGuy\\PiggyCustomEnchan"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/traits/ToggleTrait.php",
    "chars": 3947,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\traits;\n\nuse DaPigGuy\\PiggyCustomEnchan"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/BlessedEnchant.php",
    "chars": 963,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/ConditionalDamageMultiplierEnchant.php",
    "chars": 1309,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/DeathbringerEnchant.php",
    "chars": 948,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/DeepWoundsEnchant.php",
    "chars": 2181,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/DisarmingEnchant.php",
    "chars": 1101,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/DisarmorEnchant.php",
    "chars": 1058,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse pocketmine\\event\\entity\\E"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/GooeyEnchant.php",
    "chars": 1224,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/HallucinationEnchant.php",
    "chars": 5077,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/LacedWeaponEnchant.php",
    "chars": 2279,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/LifestealEnchant.php",
    "chars": 1095,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/LightningEnchant.php",
    "chars": 944,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/VampireEnchant.php",
    "chars": 1530,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons;\n\nuse DaPigGuy\\PiggyCustomEncha"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/AutoAimEnchant.php",
    "chars": 2417,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/BombardmentEnchant.php",
    "chars": 1389,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/BountyHunterEnchant.php",
    "chars": 1987,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/GrapplingEnchant.php",
    "chars": 3504,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/HeadhunterEnchant.php",
    "chars": 1423,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/HealingEnchant.php",
    "chars": 1455,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/MissileEnchant.php",
    "chars": 1448,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/MolotovEnchant.php",
    "chars": 1710,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/ParalyzeEnchant.php",
    "chars": 2865,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/PiercingEnchant.php",
    "chars": 1105,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/ProjectileChangingEnchant.php",
    "chars": 2074,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/ShuffleEnchant.php",
    "chars": 1771,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/enchants/weapons/bows/VolleyEnchant.php",
    "chars": 2656,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\enchants\\weapons\\bows;\n\nuse DaPigGuy\\PiggyCustom"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/entities/BombardmentTNT.php",
    "chars": 782,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\entities;\n\nuse pocketmine\\block\\VanillaBlocks;\nu"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/entities/HomingArrow.php",
    "chars": 2789,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\entities;\n\nuse DaPigGuy\\PiggyCustomEnchants\\util"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/entities/PigProjectile.php",
    "chars": 4538,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\entities;\n\nuse pocketmine\\entity\\Attribute;\nuse "
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/entities/PiggyFireball.php",
    "chars": 1563,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\entities;\n\nuse DaPigGuy\\PiggyCustomEnchants\\util"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/entities/PiggyLightning.php",
    "chars": 2232,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\entities;\n\nuse DaPigGuy\\PiggyCustomEnchants\\Cust"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/entities/PiggyProjectile.php",
    "chars": 419,
    "preview": "<?php\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\entities;\n\nuse pocketmine\\entity\\projectile\\Projectile;\nuse pocketmine\\eve"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/entities/PiggyTNT.php",
    "chars": 1252,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\entities;\n\nuse DaPigGuy\\PiggyCustomEnchants\\util"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/entities/PiggyWitherSkull.php",
    "chars": 1367,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\entities;\n\nuse DaPigGuy\\PiggyCustomEnchants\\util"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/particles/JetpackParticle.php",
    "chars": 461,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\particles;\n\nuse pocketmine\\math\\Vector3;\nuse poc"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/tasks/CheckDisabledEnchantsTask.php",
    "chars": 1772,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\tasks;\n\nuse DaPigGuy\\PiggyCustomEnchants\\CustomE"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/tasks/TickEnchantmentsTask.php",
    "chars": 5973,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\tasks;\n\nuse DaPigGuy\\PiggyCustomEnchants\\enchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/utils/AllyChecks.php",
    "chars": 1002,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\utils;\n\nuse pocketmine\\entity\\Entity;\nuse pocket"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/utils/PiggyExplosion.php",
    "chars": 4015,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\utils;\n\nuse DaPigGuy\\PiggyCustomEnchants\\enchant"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/utils/ProjectileTracker.php",
    "chars": 1334,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\utils;\n\nuse pocketmine\\entity\\projectile\\Project"
  },
  {
    "path": "src/DaPigGuy/PiggyCustomEnchants/utils/Utils.php",
    "chars": 13429,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DaPigGuy\\PiggyCustomEnchants\\utils;\n\nuse DaPigGuy\\PiggyCustomEnchants\\CustomE"
  }
]

About this extraction

This page contains the full source code of the DaPigGuy/PiggyCustomEnchants GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 125 files (304.9 KB), approximately 82.9k tokens, and a symbol index with 461 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!