<commit_before><?php

/**
 *
 * MMP""MM""YMM               .M"""bgd
 * P'   MM   `7              ,MI    "Y
 *      MM  .gP"Ya   ,6"Yb.  `MMb.   `7MMpdMAo.  ,pW"Wq.   ,pW"Wq.`7MMpMMMb.
 *      MM ,M'   Yb 8)   MM    `YMMNq. MM   `Wb 6W'   `Wb 6W'   `Wb MM    MM
 *      MM 8M""""""  ,pm9MM  .     `MM MM    M8 8M     M8 8M     M8 MM    MM
 *      MM YM.    , 8M   MM  Mb     dM MM   ,AP YA.   ,A9 YA.   ,A9 MM    MM
 *    .JMML.`Mbmmd' `Moo9^Yo.P"Ybmmd"  MMbmmd'   `Ybmd9'   `Ybmd9'.JMML  JMML.
 *                                     MM
 *                                   .JMML.
 * This file is part of TeaSpoon.
 *
 * TeaSpoon is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * TeaSpoon is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with TeaSpoon.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author CortexPE
 * @link https://CortexPE.xyz
 *
 */

declare(strict_types = 1);

namespace CortexPE\handlers;

use CortexPE\item\enchantment\Enchantment;
use CortexPE\Utils;
use pocketmine\block\Block;
use pocketmine\entity\Entity;
use pocketmine\entity\Human;
use pocketmine\entity\Living;
use pocketmine\event\block\BlockBreakEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityDeathEvent;
use pocketmine\event\Listener;
use pocketmine\item\Axe;
use pocketmine\item\enchantment\EnchantmentInstance;
use pocketmine\item\Item;
use pocketmine\item\Pickaxe;
use pocketmine\item\TieredTool;
use pocketmine\Player as PMPlayer;
use pocketmine\plugin\Plugin;

class EnchantHandler implements Listener {
	/**
	 * TO-DO:
	 * [X] Protection (PMMP)
	 * [X] Fire Protection (PMMP)
	 * [X] Feather Falling (PMMP)
	 * [X] Blast protection (PMMP)
	 * [X] Projectile protection (PMMP)
	 * [X] Thorns
	 * [X] Respiration (PMMP)
	 * [X] Depth strider (Client Side)
	 * [X] Aqua affinity (Client Side)
	 * [X] Sharpness
	 * [X] Smite
	 * [X] Bane of athropods
	 * [X] Knockback
	 * [X] Fire aspect
	 * [X] Looting
	 * [X] Efficiency (PMMP)
	 * [X] Silk touch (PMMP)
	 * [X] Unbreaking (PMMP)
	 * [X] Fortune
	 * [X] Power
	 * [X] Punch
	 * [X] Flame
	 * [X] Infinity
	 * [X] Luck of the sea
	 * [X] Lure
	 * [ ] Frost walker (Very laggy as of now)
	 * [ ] Mending
	 */

	/** @var string */
	public const BANE_OF_ARTHROPODS_AFFECTED_ENTITIES = [ // Based on https://minecraft.gamepedia.com/Enchanting#Bane_of_Arthropods ^_^
		"Spider", "Cave Spider",
		"Silverfish", "Endermite",
	];

	/** @var int[] */
	public const WATER_IDS = [
		Block::STILL_WATER,
		Block::FLOWING_WATER,
	];

	/** @var Plugin */
	public $plugin;

	public function __construct(Plugin $plugin){
		$this->plugin = $plugin;
	}

	/**
	 * @param EntityDamageEvent $ev
	 *
	 * @priority HIGHEST
	 */
	public function onDamage(EntityDamageEvent $ev){
		$e = $ev->getEntity();
		if($ev->isCancelled()){
			return;
		}
		if($ev instanceof EntityDamageByEntityEvent){
			$d = $ev->getDamager();
			if(!($d instanceof Entity) || !$d->isAlive()){
				return;
			}
			if($d instanceof PMPlayer && $e instanceof Living){
				$i = $d->getInventory()->getItemInHand();
				$damage = $ev->getModifier(EntityDamageEvent::MODIFIER_ARMOR);
				$knockback = $ev->getKnockBack();
				foreach(Utils::getEnchantments($i) as $ench){
					$lvl = $ench->getLevel();
					switch($ench->getId()){
						case Enchantment::FIRE_ASPECT:
							$e->setOnFire(($lvl * 4) * 20);
							break;
						case Enchantment::KNOCKBACK:
							$ev->setKnockBack(($knockback + 0.3) * $lvl);
							break;
						case Enchantment::PUNCH:
							if($d->getInventory()->getItemInHand()->getId() == Item::BOW){
								$ev->setKnockBack(($knockback + 0.2) * $lvl);
							}
							break;
						case Enchantment::BANE_OF_ARTHROPODS:
							if(Utils::in_arrayi($e->getName(), self::BANE_OF_ARTHROPODS_AFFECTED_ENTITIES)){
								$ev->setModifier($damage + ($lvl * 2.5), EntityDamageEvent::MODIFIER_ARMOR);
							}
							break;
						case Enchantment::POWER:
							if($i->getId() == Item::BOW){
								$ev->setModifier($damage + ((($damage * 0.25) * $lvl) + 1), EntityDamageEvent::MODIFIER_ARMOR);
							}
							break;
						case Enchantment::SMITE:
							$ev->setModifier($damage + ($lvl * 2.5), EntityDamageEvent::MODIFIER_ARMOR);
							break;
						case Enchantment::SHARPNESS:
							$ev->setModifier($damage + (($lvl * 0.4) + 1), EntityDamageEvent::MODIFIER_ARMOR);
							break;
					}
				}
				if($e instanceof PMPlayer){
					foreach($e->getArmorInventory()->getContents() as $armorContent){
						if($armorContent->hasEnchantment(Enchantment::THORNS)){
							$enchantment = $armorContent->getEnchantment(Enchantment::THORNS);
							if($d instanceof PMPlayer){
								$armor = $d->getArmorInventory()->getHelmet();
								if(mt_rand(1, 2) == 1 && $armor->getId() !== Block::AIR){
									$armorClone = clone $armor;
									if($armorClone->getDamage() - 3 > 0){
										$armorClone->setDamage($armorClone->getDamage() - 3);
									}else{
										$armorClone->setDamage(0);
									}
									$d->getArmorInventory()->setHelmet($armorClone);
								}
								$armor = $d->getArmorInventory()->getChestplate();
								if(mt_rand(1, 2) == 1 && $armor->getId() !== Block::AIR){
									$armorClone = clone $armor;
									if($armorClone->getDamage() - 3 > 0){
										$armorClone->setDamage($armorClone->getDamage() - 3);
									}else{
										$armorClone->setDamage(0);
									}
									$d->getArmorInventory()->setChestplate($armorClone);
								}
								$armor = $d->getArmorInventory()->getLeggings();
								if(mt_rand(1, 2) == 1 && $armor->getId() !== Block::AIR){
									$armorClone = clone $armor;
									if($armorClone->getDamage() - 3 > 0){
										$armorClone->setDamage($armorClone->getDamage() - 3);
									}else{
										$armorClone->setDamage(0);
									}
									$d->getArmorInventory()->setLeggings($armorClone);
								}
								$armor = $d->getArmorInventory()->getBoots();
								if(mt_rand(1, 2) == 1 && $armor->getId() !== Block::AIR){
									$armorClone = clone $armor;
									if($armorClone->getDamage() - 3 > 0){
										$armorClone->setDamage($armorClone->getDamage() - 3);
									}else{
										$armorClone->setDamage(0);
									}
									$d->getArmorInventory()->setBoots($armorClone);
								}
								$d->attack(new EntityDamageEvent($e, EntityDamageEvent::CAUSE_CUSTOM, mt_rand($enchantment->getLevel(), 4 + $enchantment->getLevel())));
							}
							break; // do this only once...
						}
					}
				}
			}
		}
	}

	/**
	 * @param BlockBreakEvent $ev
	 *
	 * Attribution:
	 *  - Big thanks to @TheAz928 for the values... It really helped a lot! :D
	 *  - The onBreak function below is a refactored, bare-bones and more-human friendly version of his Fortune enchant handler...
	 *
	 * @priority HIGHEST
	 */
	public function onBreak(BlockBreakEvent $ev){
		if($ev->isCancelled()){
			return;<commit_msg>Remove enchants that PMMP already implemented<commit_after><?php

/**
 *
 * MMP""MM""YMM               .M"""bgd
 * P'   MM   `7              ,MI    "Y
 *      MM  .gP"Ya   ,6"Yb.  `MMb.   `7MMpdMAo.  ,pW"Wq.   ,pW"Wq.`7MMpMMMb.
 *      MM ,M'   Yb 8)   MM    `YMMNq. MM   `Wb 6W'   `Wb 6W'   `Wb MM    MM
 *      MM 8M""""""  ,pm9MM  .     `MM MM    M8 8M     M8 8M     M8 MM    MM
 *      MM YM.    , 8M   MM  Mb     dM MM   ,AP YA.   ,A9 YA.   ,A9 MM    MM
 *    .JMML.`Mbmmd' `Moo9^Yo.P"Ybmmd"  MMbmmd'   `Ybmd9'   `Ybmd9'.JMML  JMML.
 *                                     MM
 *                                   .JMML.
 * This file is part of TeaSpoon.
 *
 * TeaSpoon is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * TeaSpoon is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with TeaSpoon.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author CortexPE
 * @link https://CortexPE.xyz
 *
 */

declare(strict_types = 1);

namespace CortexPE\handlers;

use CortexPE\item\enchantment\Enchantment;
use CortexPE\Utils;
use pocketmine\block\Block;
use pocketmine\entity\Entity;
use pocketmine\entity\Human;
use pocketmine\entity\Living;
use pocketmine\event\block\BlockBreakEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityDeathEvent;
use pocketmine\event\Listener;
use pocketmine\item\Axe;
use pocketmine\item\enchantment\EnchantmentInstance;
use pocketmine\item\Item;
use pocketmine\item\Pickaxe;
use pocketmine\item\TieredTool;
use pocketmine\Player as PMPlayer;
use pocketmine\plugin\Plugin;

class EnchantHandler implements Listener {
	/**
	 * TO-DO:
	 * [X] Smite
	 * [X] Bane of athropods
	 * [X] Knockback
	 * [X] Looting
	 * [X] Fortune
	 * [X] Luck of the sea
	 * [X] Lure
	 * [ ] Frost walker (Very laggy as of now)
	 */

	/** @var string */
	public const BANE_OF_ARTHROPODS_AFFECTED_ENTITIES = [ // Based on https://minecraft.gamepedia.com/Enchanting#Bane_of_Arthropods ^_^
		"Spider", "Cave Spider",
		"Silverfish", "Endermite",
	];

	/** @var Plugin */
	public $plugin;

	public function __construct(Plugin $plugin){
		$this->plugin = $plugin;
	}

	/**
	 * @param EntityDamageEvent $ev
	 *
	 * @priority HIGHEST
	 */
	public function onDamage(EntityDamageEvent $ev){
		$e = $ev->getEntity();
		if($ev->isCancelled()){
			return;
		}
		if($ev instanceof EntityDamageByEntityEvent){
			$d = $ev->getDamager();
			if(!($d instanceof Entity) || !$d->isAlive()){
				return;
			}
			if($d instanceof PMPlayer && $e instanceof Living){
				$i = $d->getInventory()->getItemInHand();
				$damage = $ev->getModifier(EntityDamageEvent::MODIFIER_ARMOR);
				foreach(Utils::getEnchantments($i) as $ench){
					$lvl = $ench->getLevel();
					switch($ench->getId()){
						case Enchantment::BANE_OF_ARTHROPODS:
							if(Utils::in_arrayi($e->getName(), self::BANE_OF_ARTHROPODS_AFFECTED_ENTITIES)){
								$ev->setModifier($damage + ($lvl * 2.5), EntityDamageEvent::MODIFIER_ARMOR);
							}
							break;
						case Enchantment::SMITE:
							$ev->setModifier($damage + ($lvl * 2.5), EntityDamageEvent::MODIFIER_ARMOR);
							break;
					}
				}
			}
		}
	}

	/**
	 * @param BlockBreakEvent $ev
	 *
	 * Attribution:
	 *  - Big thanks to @TheAz928 for the values... It really helped a lot! :D
	 *  - The onBreak function below is a refactored, bare-bones and more-human friendly version of his Fortune enchant handler...
	 *
	 * @priority HIGHEST
	 */
	public function onBreak(BlockBreakEvent $ev){
		if($ev->isCancelled()){
			return;
{'fraction_non_alphanumeric': 0.1454034594784441, 'fraction_numerical': 0.008868206163842304, 'mean_word_length': 2.817024128686327, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 90, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5145660', 'n_tokens_mistral': 4952, 'n_tokens_neox': 4060, 'n_words': 935}