diff --git a/src/Server.php b/src/Server.php index 1dc6d86ae..419ffdb9b 100644 --- a/src/Server.php +++ b/src/Server.php @@ -39,7 +39,6 @@ use pocketmine\event\player\PlayerDataSaveEvent; use pocketmine\event\server\CommandEvent; use pocketmine\event\server\DataPacketSendEvent; use pocketmine\event\server\QueryRegenerateEvent; -use pocketmine\item\enchantment\Enchantment; use pocketmine\lang\Language; use pocketmine\lang\LanguageNotFoundException; use pocketmine\lang\TranslationContainer; @@ -937,7 +936,6 @@ class Server{ $this->commandMap = new SimpleCommandMap($this); - Enchantment::init(); Biome::init(); $this->craftingManager = CraftingManagerFromDataHelper::make(\pocketmine\RESOURCE_PATH . '/vanilla/recipes.json'); diff --git a/src/block/Block.php b/src/block/Block.php index d81d143d8..6ac38de9f 100644 --- a/src/block/Block.php +++ b/src/block/Block.php @@ -30,7 +30,7 @@ use pocketmine\block\tile\Spawnable; use pocketmine\block\tile\Tile; use pocketmine\block\utils\InvalidBlockStateException; use pocketmine\entity\Entity; -use pocketmine\item\enchantment\Enchantment; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\math\Axis; @@ -357,7 +357,7 @@ class Block{ */ public function getDrops(Item $item) : array{ if($this->breakInfo->isToolCompatible($item)){ - if($this->isAffectedBySilkTouch() and $item->hasEnchantment(Enchantment::SILK_TOUCH())){ + if($this->isAffectedBySilkTouch() and $item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){ return $this->getSilkTouchDrops($item); } @@ -389,7 +389,7 @@ class Block{ * Returns how much XP will be dropped by breaking this block with the given item. */ public function getXpDropForTool(Item $item) : int{ - if($item->hasEnchantment(Enchantment::SILK_TOUCH()) or !$this->breakInfo->isToolCompatible($item)){ + if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH()) or !$this->breakInfo->isToolCompatible($item)){ return 0; } diff --git a/src/block/Ice.php b/src/block/Ice.php index ef2917997..b22278fb0 100644 --- a/src/block/Ice.php +++ b/src/block/Ice.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace pocketmine\block; -use pocketmine\item\enchantment\Enchantment; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\item\Item; use pocketmine\player\Player; @@ -42,7 +42,7 @@ class Ice extends Transparent{ } public function onBreak(Item $item, ?Player $player = null) : bool{ - if(($player === null or $player->isSurvival()) and !$item->hasEnchantment(Enchantment::SILK_TOUCH())){ + if(($player === null or $player->isSurvival()) and !$item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){ $this->pos->getWorld()->setBlock($this->pos, VanillaBlocks::WATER()); return true; } diff --git a/src/block/TNT.php b/src/block/TNT.php index f9325afd1..46256f929 100644 --- a/src/block/TNT.php +++ b/src/block/TNT.php @@ -28,7 +28,7 @@ use pocketmine\entity\Location; use pocketmine\entity\object\PrimedTNT; use pocketmine\entity\projectile\Arrow; use pocketmine\item\Durable; -use pocketmine\item\enchantment\Enchantment; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\item\FlintSteel; use pocketmine\item\Item; use pocketmine\math\Vector3; @@ -68,7 +68,7 @@ class TNT extends Opaque{ } public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if($item instanceof FlintSteel or $item->hasEnchantment(Enchantment::FIRE_ASPECT())){ + if($item instanceof FlintSteel or $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){ if($item instanceof Durable){ $item->applyDamage(1); } diff --git a/src/command/defaults/EnchantCommand.php b/src/command/defaults/EnchantCommand.php index bd8b71bd6..05cec32ee 100644 --- a/src/command/defaults/EnchantCommand.php +++ b/src/command/defaults/EnchantCommand.php @@ -27,6 +27,7 @@ use pocketmine\command\CommandSender; use pocketmine\command\utils\InvalidCommandSyntaxException; use pocketmine\item\enchantment\Enchantment; use pocketmine\item\enchantment\EnchantmentInstance; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\lang\TranslationContainer; use pocketmine\utils\TextFormat; use function count; @@ -67,9 +68,9 @@ class EnchantCommand extends VanillaCommand{ } if(is_numeric($args[1])){ - $enchantment = Enchantment::get((int) $args[1]); + $enchantment = VanillaEnchantments::byMcpeId((int) $args[1]); }else{ - $enchantment = Enchantment::fromString($args[1]); + $enchantment = VanillaEnchantments::fromString($args[1]); } if(!($enchantment instanceof Enchantment)){ diff --git a/src/entity/ExperienceManager.php b/src/entity/ExperienceManager.php index 9e973bc3d..223ad5ee1 100644 --- a/src/entity/ExperienceManager.php +++ b/src/entity/ExperienceManager.php @@ -26,7 +26,7 @@ namespace pocketmine\entity; use pocketmine\entity\utils\ExperienceUtils; use pocketmine\event\player\PlayerExperienceChangeEvent; use pocketmine\item\Durable; -use pocketmine\item\enchantment\Enchantment; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\world\sound\XpCollectSound; use pocketmine\world\sound\XpLevelUpSound; use function array_rand; @@ -244,12 +244,12 @@ class ExperienceManager{ /** @var Durable[] $equipment */ $equipment = []; - if(($item = $this->entity->getInventory()->getItemInHand()) instanceof Durable and $item->hasEnchantment(Enchantment::MENDING())){ + if(($item = $this->entity->getInventory()->getItemInHand()) instanceof Durable and $item->hasEnchantment(VanillaEnchantments::MENDING())){ $equipment[$mainHandIndex] = $item; } //TODO: check offhand foreach($this->entity->getArmorInventory()->getContents() as $k => $armorItem){ - if($armorItem instanceof Durable and $armorItem->hasEnchantment(Enchantment::MENDING())){ + if($armorItem instanceof Durable and $armorItem->hasEnchantment(VanillaEnchantments::MENDING())){ $equipment[$k] = $armorItem; } } diff --git a/src/entity/Human.php b/src/entity/Human.php index f85e0ab85..39a671e09 100644 --- a/src/entity/Human.php +++ b/src/entity/Human.php @@ -32,7 +32,7 @@ use pocketmine\event\entity\EntityDamageEvent; use pocketmine\event\player\PlayerExhaustEvent; use pocketmine\inventory\InventoryHolder; use pocketmine\inventory\PlayerInventory; -use pocketmine\item\enchantment\Enchantment; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\item\Item; use pocketmine\item\Totem; use pocketmine\math\Vector3; @@ -310,7 +310,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ return array_filter(array_merge( $this->inventory !== null ? array_values($this->inventory->getContents()) : [], $this->armorInventory !== null ? array_values($this->armorInventory->getContents()) : [] - ), function(Item $item) : bool{ return !$item->hasEnchantment(Enchantment::VANISHING()); }); + ), function(Item $item) : bool{ return !$item->hasEnchantment(VanillaEnchantments::VANISHING()); }); } public function saveNBT() : CompoundTag{ diff --git a/src/entity/Living.php b/src/entity/Living.php index 89d26927f..cc9a0334f 100644 --- a/src/entity/Living.php +++ b/src/entity/Living.php @@ -41,6 +41,7 @@ use pocketmine\inventory\Inventory; use pocketmine\item\Armor; use pocketmine\item\Durable; use pocketmine\item\enchantment\Enchantment; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\item\Item; use pocketmine\math\Vector3; use pocketmine\math\VoxelRayTrace; @@ -346,7 +347,7 @@ abstract class Living extends Entity{ } public function setOnFire(int $seconds) : void{ - parent::setOnFire($seconds - (int) min($seconds, $seconds * $this->getHighestArmorEnchantmentLevel(Enchantment::FIRE_PROTECTION()) * 0.15)); + parent::setOnFire($seconds - (int) min($seconds, $seconds * $this->getHighestArmorEnchantmentLevel(VanillaEnchantments::FIRE_PROTECTION()) * 0.15)); } /** @@ -393,7 +394,7 @@ abstract class Living extends Entity{ if($source instanceof EntityDamageByEntityEvent and ($attacker = $source->getDamager()) !== null){ $damage = 0; foreach($this->armorInventory->getContents() as $k => $item){ - if($item instanceof Armor and ($thornsLevel = $item->getEnchantmentLevel(Enchantment::THORNS())) > 0){ + if($item instanceof Armor and ($thornsLevel = $item->getEnchantmentLevel(VanillaEnchantments::THORNS())) > 0){ if(mt_rand(0, 99) < $thornsLevel * 15){ $this->damageItem($item, 3); $damage += ($thornsLevel > 10 ? $thornsLevel - 10 : 1 + mt_rand(0, 3)); @@ -458,7 +459,7 @@ abstract class Living extends Entity{ //TODO: knockback should not just apply for entity damage sources //this doesn't matter for TNT right now because the PrimedTNT entity is considered the source, not the block. $base = $source->getKnockBack(); - $source->setKnockBack($base - min($base, $base * $this->getHighestArmorEnchantmentLevel(Enchantment::BLAST_PROTECTION()) * 0.15)); + $source->setKnockBack($base - min($base, $base * $this->getHighestArmorEnchantmentLevel(VanillaEnchantments::BLAST_PROTECTION()) * 0.15)); } parent::attack($source); @@ -588,7 +589,7 @@ abstract class Living extends Entity{ if(!$this->canBreathe()){ $this->setBreathing(false); - if(($respirationLevel = $this->armorInventory->getHelmet()->getEnchantmentLevel(Enchantment::RESPIRATION())) <= 0 or + if(($respirationLevel = $this->armorInventory->getHelmet()->getEnchantmentLevel(VanillaEnchantments::RESPIRATION())) <= 0 or lcg_value() <= (1 / ($respirationLevel + 1)) ){ $ticks -= $tickDiff; diff --git a/src/item/Armor.php b/src/item/Armor.php index 4f79d9c61..a3e235ded 100644 --- a/src/item/Armor.php +++ b/src/item/Armor.php @@ -27,8 +27,8 @@ use pocketmine\block\Block; use pocketmine\color\Color; use pocketmine\event\entity\EntityDamageEvent; use pocketmine\inventory\ArmorInventory; -use pocketmine\item\enchantment\Enchantment; use pocketmine\item\enchantment\ProtectionEnchantment; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; @@ -106,7 +106,7 @@ class Armor extends Durable{ } protected function getUnbreakingDamageReduction(int $amount) : int{ - if(($unbreakingLevel = $this->getEnchantmentLevel(Enchantment::UNBREAKING())) > 0){ + if(($unbreakingLevel = $this->getEnchantmentLevel(VanillaEnchantments::UNBREAKING())) > 0){ $negated = 0; $chance = 1 / ($unbreakingLevel + 1); diff --git a/src/item/Bow.php b/src/item/Bow.php index d57bff29b..c86438b3b 100644 --- a/src/item/Bow.php +++ b/src/item/Bow.php @@ -28,7 +28,7 @@ use pocketmine\entity\projectile\Arrow as ArrowEntity; use pocketmine\entity\projectile\Projectile; use pocketmine\event\entity\EntityShootBowEvent; use pocketmine\event\entity\ProjectileLaunchEvent; -use pocketmine\item\enchantment\Enchantment; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\player\Player; use pocketmine\world\sound\BowShootSound; use function intdiv; @@ -64,17 +64,17 @@ class Bow extends Tool implements Releasable{ ), $player, $baseForce >= 1); $entity->setMotion($player->getDirectionVector()); - $infinity = $this->hasEnchantment(Enchantment::INFINITY()); + $infinity = $this->hasEnchantment(VanillaEnchantments::INFINITY()); if($infinity){ $entity->setPickupMode(ArrowEntity::PICKUP_CREATIVE); } - if(($punchLevel = $this->getEnchantmentLevel(Enchantment::PUNCH())) > 0){ + if(($punchLevel = $this->getEnchantmentLevel(VanillaEnchantments::PUNCH())) > 0){ $entity->setPunchKnockback($punchLevel); } - if(($powerLevel = $this->getEnchantmentLevel(Enchantment::POWER())) > 0){ + if(($powerLevel = $this->getEnchantmentLevel(VanillaEnchantments::POWER())) > 0){ $entity->setBaseDamage($entity->getBaseDamage() + (($powerLevel + 1) / 2)); } - if($this->hasEnchantment(Enchantment::FLAME())){ + if($this->hasEnchantment(VanillaEnchantments::FLAME())){ $entity->setOnFire(intdiv($entity->getFireTicks(), 20) + 100); } $ev = new EntityShootBowEvent($player, $this, $entity, $baseForce * 3); diff --git a/src/item/Durable.php b/src/item/Durable.php index a84956d0b..004525808 100644 --- a/src/item/Durable.php +++ b/src/item/Durable.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace pocketmine\item; -use pocketmine\item\enchantment\Enchantment; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\nbt\tag\CompoundTag; use function lcg_value; use function min; @@ -89,7 +89,7 @@ abstract class Durable extends Item{ } protected function getUnbreakingDamageReduction(int $amount) : int{ - if(($unbreakingLevel = $this->getEnchantmentLevel(Enchantment::UNBREAKING())) > 0){ + if(($unbreakingLevel = $this->getEnchantmentLevel(VanillaEnchantments::UNBREAKING())) > 0){ $negated = 0; $chance = 1 / ($unbreakingLevel + 1); diff --git a/src/item/Item.php b/src/item/Item.php index 7cbbddb54..7228c15cd 100644 --- a/src/item/Item.php +++ b/src/item/Item.php @@ -32,8 +32,8 @@ use pocketmine\block\BlockBreakInfo; use pocketmine\block\BlockToolType; use pocketmine\block\VanillaBlocks; use pocketmine\entity\Entity; -use pocketmine\item\enchantment\Enchantment; use pocketmine\item\enchantment\EnchantmentInstance; +use pocketmine\item\enchantment\VanillaEnchantments; use pocketmine\math\Vector3; use pocketmine\nbt\LittleEndianNbtSerializer; use pocketmine\nbt\NBT; @@ -285,7 +285,7 @@ class Item implements \JsonSerializable{ if($level <= 0){ continue; } - $type = Enchantment::get($magicNumber); + $type = VanillaEnchantments::byMcpeId($magicNumber); if($type !== null){ $this->addEnchantment(new EnchantmentInstance($type, $level)); } diff --git a/src/item/Tool.php b/src/item/Tool.php index 47a9b651b..d6cc1a061 100644 --- a/src/item/Tool.php +++ b/src/item/Tool.php @@ -23,7 +23,7 @@ declare(strict_types=1); namespace pocketmine\item; -use pocketmine\item\enchantment\Enchantment; +use pocketmine\item\enchantment\VanillaEnchantments; abstract class Tool extends Durable{ @@ -35,7 +35,7 @@ abstract class Tool extends Durable{ $efficiency = 1; if($isCorrectTool){ $efficiency = $this->getBaseMiningEfficiency(); - if(($enchantmentLevel = $this->getEnchantmentLevel(Enchantment::EFFICIENCY())) > 0){ + if(($enchantmentLevel = $this->getEnchantmentLevel(VanillaEnchantments::EFFICIENCY())) > 0){ $efficiency += ($enchantmentLevel ** 2 + 1); } } diff --git a/src/item/enchantment/Enchantment.php b/src/item/enchantment/Enchantment.php index 50ac2d406..85c321d36 100644 --- a/src/item/enchantment/Enchantment.php +++ b/src/item/enchantment/Enchantment.php @@ -23,10 +23,7 @@ declare(strict_types=1); namespace pocketmine\item\enchantment; -use pocketmine\event\entity\EntityDamageEvent; use function constant; -use function defined; -use function mb_strtoupper; /** * Manages enchantment type data. @@ -98,149 +95,6 @@ class Enchantment{ public const SLOT_ELYTRA = 0x4000; public const SLOT_TRIDENT = 0x8000; - /** @var Enchantment[] */ - protected static $enchantments = []; - - public static function init() : void{ - self::register(new ProtectionEnchantment(self::PROTECTION, "%enchantment.protect.all", self::RARITY_COMMON, self::SLOT_ARMOR, self::SLOT_NONE, 4, 0.75, null)); - self::register(new ProtectionEnchantment(self::FIRE_PROTECTION, "%enchantment.protect.fire", self::RARITY_UNCOMMON, self::SLOT_ARMOR, self::SLOT_NONE, 4, 1.25, [ - EntityDamageEvent::CAUSE_FIRE, - EntityDamageEvent::CAUSE_FIRE_TICK, - EntityDamageEvent::CAUSE_LAVA - //TODO: check fireballs - ])); - self::register(new ProtectionEnchantment(self::FEATHER_FALLING, "%enchantment.protect.fall", self::RARITY_UNCOMMON, self::SLOT_FEET, self::SLOT_NONE, 4, 2.5, [ - EntityDamageEvent::CAUSE_FALL - ])); - self::register(new ProtectionEnchantment(self::BLAST_PROTECTION, "%enchantment.protect.explosion", self::RARITY_RARE, self::SLOT_ARMOR, self::SLOT_NONE, 4, 1.5, [ - EntityDamageEvent::CAUSE_BLOCK_EXPLOSION, - EntityDamageEvent::CAUSE_ENTITY_EXPLOSION - ])); - self::register(new ProtectionEnchantment(self::PROJECTILE_PROTECTION, "%enchantment.protect.projectile", self::RARITY_UNCOMMON, self::SLOT_ARMOR, self::SLOT_NONE, 4, 1.5, [ - EntityDamageEvent::CAUSE_PROJECTILE - ])); - self::register(new Enchantment(self::THORNS, "%enchantment.thorns", self::RARITY_MYTHIC, self::SLOT_TORSO, self::SLOT_HEAD | self::SLOT_LEGS | self::SLOT_FEET, 3)); - self::register(new Enchantment(self::RESPIRATION, "%enchantment.oxygen", self::RARITY_RARE, self::SLOT_HEAD, self::SLOT_NONE, 3)); - - self::register(new SharpnessEnchantment(self::SHARPNESS, "%enchantment.damage.all", self::RARITY_COMMON, self::SLOT_SWORD, self::SLOT_AXE, 5)); - //TODO: smite, bane of arthropods (these don't make sense now because their applicable mobs don't exist yet) - - self::register(new KnockbackEnchantment(self::KNOCKBACK, "%enchantment.knockback", self::RARITY_UNCOMMON, self::SLOT_SWORD, self::SLOT_NONE, 2)); - self::register(new FireAspectEnchantment(self::FIRE_ASPECT, "%enchantment.fire", self::RARITY_RARE, self::SLOT_SWORD, self::SLOT_NONE, 2)); - - self::register(new Enchantment(self::EFFICIENCY, "%enchantment.digging", self::RARITY_COMMON, self::SLOT_DIG, self::SLOT_SHEARS, 5)); - self::register(new Enchantment(self::SILK_TOUCH, "%enchantment.untouching", self::RARITY_MYTHIC, self::SLOT_DIG, self::SLOT_SHEARS, 1)); - self::register(new Enchantment(self::UNBREAKING, "%enchantment.durability", self::RARITY_UNCOMMON, self::SLOT_DIG | self::SLOT_ARMOR | self::SLOT_FISHING_ROD | self::SLOT_BOW, self::SLOT_TOOL | self::SLOT_CARROT_STICK | self::SLOT_ELYTRA, 3)); - - self::register(new Enchantment(self::POWER, "%enchantment.arrowDamage", self::RARITY_COMMON, self::SLOT_BOW, self::SLOT_NONE, 5)); - self::register(new Enchantment(self::PUNCH, "%enchantment.arrowKnockback", self::RARITY_RARE, self::SLOT_BOW, self::SLOT_NONE, 2)); - self::register(new Enchantment(self::FLAME, "%enchantment.arrowFire", self::RARITY_RARE, self::SLOT_BOW, self::SLOT_NONE, 1)); - self::register(new Enchantment(self::INFINITY, "%enchantment.arrowInfinite", self::RARITY_MYTHIC, self::SLOT_BOW, self::SLOT_NONE, 1)); - - self::register(new Enchantment(self::MENDING, "%enchantment.mending", self::RARITY_RARE, self::SLOT_NONE, self::SLOT_ALL, 1)); - - self::register(new Enchantment(self::VANISHING, "%enchantment.curse.vanishing", self::RARITY_MYTHIC, self::SLOT_NONE, self::SLOT_ALL, 1)); - } - - //region --- auto-generated code --- - - public static function BLAST_PROTECTION() : Enchantment{ - return self::get(self::BLAST_PROTECTION); - } - - public static function EFFICIENCY() : Enchantment{ - return self::get(self::EFFICIENCY); - } - - public static function FEATHER_FALLING() : Enchantment{ - return self::get(self::FEATHER_FALLING); - } - - public static function FIRE_ASPECT() : Enchantment{ - return self::get(self::FIRE_ASPECT); - } - - public static function FIRE_PROTECTION() : Enchantment{ - return self::get(self::FIRE_PROTECTION); - } - - public static function FLAME() : Enchantment{ - return self::get(self::FLAME); - } - - public static function INFINITY() : Enchantment{ - return self::get(self::INFINITY); - } - - public static function KNOCKBACK() : Enchantment{ - return self::get(self::KNOCKBACK); - } - - public static function MENDING() : Enchantment{ - return self::get(self::MENDING); - } - - public static function POWER() : Enchantment{ - return self::get(self::POWER); - } - - public static function PROJECTILE_PROTECTION() : Enchantment{ - return self::get(self::PROJECTILE_PROTECTION); - } - - public static function PROTECTION() : Enchantment{ - return self::get(self::PROTECTION); - } - - public static function PUNCH() : Enchantment{ - return self::get(self::PUNCH); - } - - public static function RESPIRATION() : Enchantment{ - return self::get(self::RESPIRATION); - } - - public static function SHARPNESS() : Enchantment{ - return self::get(self::SHARPNESS); - } - - public static function SILK_TOUCH() : Enchantment{ - return self::get(self::SILK_TOUCH); - } - - public static function THORNS() : Enchantment{ - return self::get(self::THORNS); - } - - public static function UNBREAKING() : Enchantment{ - return self::get(self::UNBREAKING); - } - - public static function VANISHING() : Enchantment{ - return self::get(self::VANISHING); - } - - //endregion - - /** - * Registers an enchantment type. - */ - public static function register(Enchantment $enchantment) : void{ - self::$enchantments[$enchantment->getId()] = clone $enchantment; - } - - public static function get(int $id) : ?Enchantment{ - return self::$enchantments[$id] ?? null; - } - - public static function fromString(string $name) : ?Enchantment{ - $const = Enchantment::class . "::" . mb_strtoupper($name); - if(defined($const)){ - return self::get(constant($const)); - } - return null; - } - /** @var int */ private $id; /** @var string */ diff --git a/src/item/enchantment/VanillaEnchantments.php b/src/item/enchantment/VanillaEnchantments.php new file mode 100644 index 000000000..8bbdd87f3 --- /dev/null +++ b/src/item/enchantment/VanillaEnchantments.php @@ -0,0 +1,137 @@ + + */ + private static $mcpeIdMap = []; + + protected static function setup() : void{ + self::register("PROTECTION", new ProtectionEnchantment(Enchantment::PROTECTION, "%enchantment.protect.all", Enchantment::RARITY_COMMON, Enchantment::SLOT_ARMOR, Enchantment::SLOT_NONE, 4, 0.75, null)); + self::register("FIRE_PROTECTION", new ProtectionEnchantment(Enchantment::FIRE_PROTECTION, "%enchantment.protect.fire", Enchantment::RARITY_UNCOMMON, Enchantment::SLOT_ARMOR, Enchantment::SLOT_NONE, 4, 1.25, [ + EntityDamageEvent::CAUSE_FIRE, + EntityDamageEvent::CAUSE_FIRE_TICK, + EntityDamageEvent::CAUSE_LAVA + //TODO: check fireballs + ])); + self::register("FEATHER_FALLING", new ProtectionEnchantment(Enchantment::FEATHER_FALLING, "%enchantment.protect.fall", Enchantment::RARITY_UNCOMMON, Enchantment::SLOT_FEET, Enchantment::SLOT_NONE, 4, 2.5, [ + EntityDamageEvent::CAUSE_FALL + ])); + self::register("BLAST_PROTECTION", new ProtectionEnchantment(Enchantment::BLAST_PROTECTION, "%enchantment.protect.explosion", Enchantment::RARITY_RARE, Enchantment::SLOT_ARMOR, Enchantment::SLOT_NONE, 4, 1.5, [ + EntityDamageEvent::CAUSE_BLOCK_EXPLOSION, + EntityDamageEvent::CAUSE_ENTITY_EXPLOSION + ])); + self::register("PROJECTILE_PROTECTION", new ProtectionEnchantment(Enchantment::PROJECTILE_PROTECTION, "%enchantment.protect.projectile", Enchantment::RARITY_UNCOMMON, Enchantment::SLOT_ARMOR, Enchantment::SLOT_NONE, 4, 1.5, [ + EntityDamageEvent::CAUSE_PROJECTILE + ])); + self::register("THORNS", new Enchantment(Enchantment::THORNS, "%enchantment.thorns", Enchantment::RARITY_MYTHIC, Enchantment::SLOT_TORSO, Enchantment::SLOT_HEAD | Enchantment::SLOT_LEGS | Enchantment::SLOT_FEET, 3)); + self::register("RESPIRATION", new Enchantment(Enchantment::RESPIRATION, "%enchantment.oxygen", Enchantment::RARITY_RARE, Enchantment::SLOT_HEAD, Enchantment::SLOT_NONE, 3)); + + self::register("SHARPNESS", new SharpnessEnchantment(Enchantment::SHARPNESS, "%enchantment.damage.all", Enchantment::RARITY_COMMON, Enchantment::SLOT_SWORD, Enchantment::SLOT_AXE, 5)); + //TODO: smite, bane of arthropods (these don't make sense now because their applicable mobs don't exist yet) + + self::register("KNOCKBACK", new KnockbackEnchantment(Enchantment::KNOCKBACK, "%enchantment.knockback", Enchantment::RARITY_UNCOMMON, Enchantment::SLOT_SWORD, Enchantment::SLOT_NONE, 2)); + self::register("FIRE_ASPECT", new FireAspectEnchantment(Enchantment::FIRE_ASPECT, "%enchantment.fire", Enchantment::RARITY_RARE, Enchantment::SLOT_SWORD, Enchantment::SLOT_NONE, 2)); + + self::register("EFFICIENCY", new Enchantment(Enchantment::EFFICIENCY, "%enchantment.digging", Enchantment::RARITY_COMMON, Enchantment::SLOT_DIG, Enchantment::SLOT_SHEARS, 5)); + self::register("SILK_TOUCH", new Enchantment(Enchantment::SILK_TOUCH, "%enchantment.untouching", Enchantment::RARITY_MYTHIC, Enchantment::SLOT_DIG, Enchantment::SLOT_SHEARS, 1)); + self::register("UNBREAKING", new Enchantment(Enchantment::UNBREAKING, "%enchantment.durability", Enchantment::RARITY_UNCOMMON, Enchantment::SLOT_DIG | Enchantment::SLOT_ARMOR | Enchantment::SLOT_FISHING_ROD | Enchantment::SLOT_BOW, Enchantment::SLOT_TOOL | Enchantment::SLOT_CARROT_STICK | Enchantment::SLOT_ELYTRA, 3)); + + self::register("POWER", new Enchantment(Enchantment::POWER, "%enchantment.arrowDamage", Enchantment::RARITY_COMMON, Enchantment::SLOT_BOW, Enchantment::SLOT_NONE, 5)); + self::register("PUNCH", new Enchantment(Enchantment::PUNCH, "%enchantment.arrowKnockback", Enchantment::RARITY_RARE, Enchantment::SLOT_BOW, Enchantment::SLOT_NONE, 2)); + self::register("FLAME", new Enchantment(Enchantment::FLAME, "%enchantment.arrowFire", Enchantment::RARITY_RARE, Enchantment::SLOT_BOW, Enchantment::SLOT_NONE, 1)); + self::register("INFINITY", new Enchantment(Enchantment::INFINITY, "%enchantment.arrowInfinite", Enchantment::RARITY_MYTHIC, Enchantment::SLOT_BOW, Enchantment::SLOT_NONE, 1)); + + self::register("MENDING", new Enchantment(Enchantment::MENDING, "%enchantment.mending", Enchantment::RARITY_RARE, Enchantment::SLOT_NONE, Enchantment::SLOT_ALL, 1)); + + self::register("VANISHING", new Enchantment(Enchantment::VANISHING, "%enchantment.curse.vanishing", Enchantment::RARITY_MYTHIC, Enchantment::SLOT_NONE, Enchantment::SLOT_ALL, 1)); + } + + protected static function register(string $name, Enchantment $member) : void{ + if(array_key_exists($member->getId(), self::$mcpeIdMap)){ + throw new \InvalidArgumentException("MCPE enchantment ID " . $member->getId() . " is already assigned"); + } + self::_registryRegister($name, $member); + self::$mcpeIdMap[$member->getId()] = $member; + } + + public static function byMcpeId(int $id) : ?Enchantment{ + //TODO: this shouldn't be in here, it's unnecessarily limiting + self::checkInit(); + return self::$mcpeIdMap[$id] ?? null; + } + + /** + * @return Enchantment[] + * @phpstan-return array + */ + public static function getAll() : array{ + /** + * @var Enchantment[] $result + * @phpstan-var array $result + */ + $result = self::_registryGetAll(); + return $result; + } + + public static function fromString(string $name) : Enchantment{ + /** @var Enchantment $result */ + $result = self::_registryFromString($name); + return $result; + } +} diff --git a/tests/phpunit/item/ItemTest.php b/tests/phpunit/item/ItemTest.php index 6a7f14dad..2340ff97d 100644 --- a/tests/phpunit/item/ItemTest.php +++ b/tests/phpunit/item/ItemTest.php @@ -24,15 +24,11 @@ declare(strict_types=1); namespace pocketmine\item; use PHPUnit\Framework\TestCase; -use pocketmine\item\enchantment\Enchantment; use pocketmine\item\enchantment\EnchantmentInstance; +use pocketmine\item\enchantment\VanillaEnchantments; class ItemTest extends TestCase{ - public static function setUpBeforeClass() : void{ - Enchantment::init(); - } - /** @var Item */ private $item; @@ -75,27 +71,27 @@ class ItemTest extends TestCase{ } public function testHasEnchantment() : void{ - $this->item->addEnchantment(new EnchantmentInstance(Enchantment::EFFICIENCY(), 5)); - self::assertTrue($this->item->hasEnchantment(Enchantment::EFFICIENCY())); - self::assertTrue($this->item->hasEnchantment(Enchantment::EFFICIENCY(), 5)); + $this->item->addEnchantment(new EnchantmentInstance(VanillaEnchantments::EFFICIENCY(), 5)); + self::assertTrue($this->item->hasEnchantment(VanillaEnchantments::EFFICIENCY())); + self::assertTrue($this->item->hasEnchantment(VanillaEnchantments::EFFICIENCY(), 5)); } public function testHasEnchantments() : void{ self::assertFalse($this->item->hasEnchantments()); - $this->item->addEnchantment(new EnchantmentInstance(Enchantment::FIRE_ASPECT())); + $this->item->addEnchantment(new EnchantmentInstance(VanillaEnchantments::FIRE_ASPECT())); self::assertTrue($this->item->hasEnchantments()); } public function testGetEnchantmentLevel() : void{ - $this->item->addEnchantment(new EnchantmentInstance(Enchantment::EFFICIENCY(), 5)); - self::assertSame(5, $this->item->getEnchantmentLevel(Enchantment::EFFICIENCY())); + $this->item->addEnchantment(new EnchantmentInstance(VanillaEnchantments::EFFICIENCY(), 5)); + self::assertSame(5, $this->item->getEnchantmentLevel(VanillaEnchantments::EFFICIENCY())); } public function testGetEnchantments() : void{ /** @var EnchantmentInstance[] $enchantments */ $enchantments = [ - new EnchantmentInstance(Enchantment::EFFICIENCY(), 5), - new EnchantmentInstance(Enchantment::SHARPNESS(), 1) + new EnchantmentInstance(VanillaEnchantments::EFFICIENCY(), 5), + new EnchantmentInstance(VanillaEnchantments::SHARPNESS(), 1) ]; foreach($enchantments as $enchantment){ $this->item->addEnchantment($enchantment); @@ -113,31 +109,31 @@ class ItemTest extends TestCase{ } public function testOverwriteEnchantment() : void{ - $this->item->addEnchantment(new EnchantmentInstance(Enchantment::SHARPNESS())); - $this->item->addEnchantment(new EnchantmentInstance(Enchantment::SHARPNESS(), 5)); - self::assertSame(5, $this->item->getEnchantmentLevel(Enchantment::SHARPNESS())); + $this->item->addEnchantment(new EnchantmentInstance(VanillaEnchantments::SHARPNESS())); + $this->item->addEnchantment(new EnchantmentInstance(VanillaEnchantments::SHARPNESS(), 5)); + self::assertSame(5, $this->item->getEnchantmentLevel(VanillaEnchantments::SHARPNESS())); } public function testRemoveAllEnchantments() : void{ - $this->item->addEnchantment(new EnchantmentInstance(Enchantment::FIRE_ASPECT())); + $this->item->addEnchantment(new EnchantmentInstance(VanillaEnchantments::FIRE_ASPECT())); self::assertCount(1, $this->item->getEnchantments()); $this->item->removeEnchantments(); self::assertEmpty($this->item->getEnchantments()); } public function testRemoveEnchantment() : void{ - $this->item->addEnchantment(new EnchantmentInstance(Enchantment::KNOCKBACK())); - $this->item->addEnchantment(new EnchantmentInstance(Enchantment::SHARPNESS())); + $this->item->addEnchantment(new EnchantmentInstance(VanillaEnchantments::KNOCKBACK())); + $this->item->addEnchantment(new EnchantmentInstance(VanillaEnchantments::SHARPNESS())); self::assertCount(2, $this->item->getEnchantments()); - $this->item->removeEnchantment(Enchantment::SHARPNESS()); - self::assertFalse($this->item->hasEnchantment(Enchantment::SHARPNESS())); + $this->item->removeEnchantment(VanillaEnchantments::SHARPNESS()); + self::assertFalse($this->item->hasEnchantment(VanillaEnchantments::SHARPNESS())); } public function testRemoveEnchantmentLevel() : void{ - $this->item->addEnchantment(new EnchantmentInstance(Enchantment::FIRE_ASPECT(), 2)); - $this->item->addEnchantment(new EnchantmentInstance(Enchantment::UNBREAKING())); + $this->item->addEnchantment(new EnchantmentInstance(VanillaEnchantments::FIRE_ASPECT(), 2)); + $this->item->addEnchantment(new EnchantmentInstance(VanillaEnchantments::UNBREAKING())); self::assertCount(2, $this->item->getEnchantments()); - $this->item->removeEnchantment(Enchantment::FIRE_ASPECT(), 2); - self::assertFalse($this->item->hasEnchantment(Enchantment::FIRE_ASPECT())); + $this->item->removeEnchantment(VanillaEnchantments::FIRE_ASPECT(), 2); + self::assertFalse($this->item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())); } }