mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-06 11:57:10 +00:00
Moved enchantment ID handling to pocketmine/data/bedrock package
this permits plugins to register their own enchantments mapped to MCPE IDs again.
This commit is contained in:
parent
2e1239f77a
commit
47976bac34
95
src/data/bedrock/EnchantmentIdMap.php
Normal file
95
src/data/bedrock/EnchantmentIdMap.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\bedrock;
|
||||
|
||||
use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\enchantment\EnchantmentIds;
|
||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use function array_key_exists;
|
||||
|
||||
/**
|
||||
* Handles translation of internal enchantment types to and from Minecraft: Bedrock IDs.
|
||||
*/
|
||||
final class EnchantmentIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var Enchantment[]
|
||||
* @phpstan-var array<int, Enchantment>
|
||||
*/
|
||||
private $idToEnch = [];
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private $enchToId = [];
|
||||
|
||||
private function __construct(){
|
||||
$this->register(EnchantmentIds::PROTECTION, VanillaEnchantments::PROTECTION());
|
||||
$this->register(EnchantmentIds::FIRE_PROTECTION, VanillaEnchantments::FIRE_PROTECTION());
|
||||
$this->register(EnchantmentIds::FEATHER_FALLING, VanillaEnchantments::FEATHER_FALLING());
|
||||
$this->register(EnchantmentIds::BLAST_PROTECTION, VanillaEnchantments::BLAST_PROTECTION());
|
||||
$this->register(EnchantmentIds::PROJECTILE_PROTECTION, VanillaEnchantments::PROJECTILE_PROTECTION());
|
||||
$this->register(EnchantmentIds::THORNS, VanillaEnchantments::THORNS());
|
||||
$this->register(EnchantmentIds::RESPIRATION, VanillaEnchantments::RESPIRATION());
|
||||
|
||||
$this->register(EnchantmentIds::SHARPNESS, VanillaEnchantments::SHARPNESS());
|
||||
//TODO: smite, bane of arthropods (these don't make sense now because their applicable mobs don't exist yet)
|
||||
|
||||
$this->register(EnchantmentIds::KNOCKBACK, VanillaEnchantments::KNOCKBACK());
|
||||
$this->register(EnchantmentIds::FIRE_ASPECT, VanillaEnchantments::FIRE_ASPECT());
|
||||
|
||||
$this->register(EnchantmentIds::EFFICIENCY, VanillaEnchantments::EFFICIENCY());
|
||||
$this->register(EnchantmentIds::SILK_TOUCH, VanillaEnchantments::SILK_TOUCH());
|
||||
$this->register(EnchantmentIds::UNBREAKING, VanillaEnchantments::UNBREAKING());
|
||||
|
||||
$this->register(EnchantmentIds::POWER, VanillaEnchantments::POWER());
|
||||
$this->register(EnchantmentIds::PUNCH, VanillaEnchantments::PUNCH());
|
||||
$this->register(EnchantmentIds::FLAME, VanillaEnchantments::FLAME());
|
||||
$this->register(EnchantmentIds::INFINITY, VanillaEnchantments::INFINITY());
|
||||
|
||||
$this->register(EnchantmentIds::MENDING, VanillaEnchantments::MENDING());
|
||||
|
||||
$this->register(EnchantmentIds::VANISHING, VanillaEnchantments::VANISHING());
|
||||
}
|
||||
|
||||
public function register(int $mcpeId, Enchantment $enchantment) : void{
|
||||
$this->idToEnch[$mcpeId] = $enchantment;
|
||||
$this->enchToId[$enchantment->getRuntimeId()] = $mcpeId;
|
||||
}
|
||||
|
||||
public function fromId(int $id) : ?Enchantment{
|
||||
//we might not have all the enchantment IDs registered
|
||||
return $this->idToEnch[$id] ?? null;
|
||||
}
|
||||
|
||||
public function toId(Enchantment $enchantment) : int{
|
||||
if(!array_key_exists($enchantment->getRuntimeId(), $this->enchToId)){
|
||||
//this should never happen, so we treat it as an exceptional condition
|
||||
throw new \InvalidArgumentException("Enchantment does not have a mapped ID");
|
||||
}
|
||||
return $this->enchToId[$enchantment->getRuntimeId()];
|
||||
}
|
||||
}
|
@ -31,9 +31,9 @@ use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockBreakInfo;
|
||||
use pocketmine\block\BlockToolType;
|
||||
use pocketmine\block\VanillaBlocks;
|
||||
use pocketmine\data\bedrock\EnchantmentIdMap;
|
||||
use pocketmine\entity\Entity;
|
||||
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 = VanillaEnchantments::byMcpeId($magicNumber);
|
||||
$type = EnchantmentIdMap::getInstance()->fromId($magicNumber);
|
||||
if($type !== null){
|
||||
$this->addEnchantment(new EnchantmentInstance($type, $level));
|
||||
}
|
||||
@ -336,7 +336,7 @@ class Item implements \JsonSerializable{
|
||||
$ench = new ListTag();
|
||||
foreach($this->getEnchantments() as $enchantmentInstance){
|
||||
$ench->push(CompoundTag::create()
|
||||
->setShort("id", $enchantmentInstance->getType()->getId())
|
||||
->setShort("id", EnchantmentIdMap::getInstance()->toId($enchantmentInstance->getType()))
|
||||
->setShort("lvl", $enchantmentInstance->getLevel())
|
||||
);
|
||||
}
|
||||
|
@ -40,12 +40,12 @@ trait ItemEnchantmentHandlingTrait{
|
||||
}
|
||||
|
||||
public function hasEnchantment(Enchantment $enchantment, int $level = -1) : bool{
|
||||
$id = $enchantment->getId();
|
||||
$id = $enchantment->getRuntimeId();
|
||||
return isset($this->enchantments[$id]) and ($level === -1 or $this->enchantments[$id]->getLevel() === $level);
|
||||
}
|
||||
|
||||
public function getEnchantment(Enchantment $enchantment) : ?EnchantmentInstance{
|
||||
return $this->enchantments[$enchantment->getId()] ?? null;
|
||||
return $this->enchantments[$enchantment->getRuntimeId()] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,7 +54,7 @@ trait ItemEnchantmentHandlingTrait{
|
||||
public function removeEnchantment(Enchantment $enchantment, int $level = -1) : self{
|
||||
$instance = $this->getEnchantment($enchantment);
|
||||
if($instance !== null and ($level === -1 or $instance->getLevel() === $level)){
|
||||
unset($this->enchantments[$enchantment->getId()]);
|
||||
unset($this->enchantments[$enchantment->getRuntimeId()]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
@ -72,7 +72,7 @@ trait ItemEnchantmentHandlingTrait{
|
||||
* @return $this
|
||||
*/
|
||||
public function addEnchantment(EnchantmentInstance $enchantment) : self{
|
||||
$this->enchantments[$enchantment->getId()] = $enchantment;
|
||||
$this->enchantments[$enchantment->getRuntimeId()] = $enchantment;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ use function constant;
|
||||
class Enchantment{
|
||||
|
||||
/** @var int */
|
||||
private $id;
|
||||
private $internalRuntimeId;
|
||||
/** @var string */
|
||||
private $name;
|
||||
/** @var int */
|
||||
@ -43,8 +43,8 @@ class Enchantment{
|
||||
/** @var int */
|
||||
private $maxLevel;
|
||||
|
||||
public function __construct(int $id, string $name, int $rarity, int $primaryItemFlags, int $secondaryItemFlags, int $maxLevel){
|
||||
$this->id = $id;
|
||||
public function __construct(int $internalRuntimeId, string $name, int $rarity, int $primaryItemFlags, int $secondaryItemFlags, int $maxLevel){
|
||||
$this->internalRuntimeId = $internalRuntimeId;
|
||||
$this->name = $name;
|
||||
$this->rarity = $rarity;
|
||||
$this->primaryItemFlags = $primaryItemFlags;
|
||||
@ -53,10 +53,11 @@ class Enchantment{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of this enchantment as per Minecraft PE
|
||||
* Returns the internal runtime ID of this enchantment.
|
||||
* WARNING: DO NOT STORE THIS IDENTIFIER - IT MAY CHANGE AFTER RESTART
|
||||
*/
|
||||
public function getId() : int{
|
||||
return $this->id;
|
||||
public function getRuntimeId() : int{
|
||||
return $this->internalRuntimeId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,10 +53,11 @@ final class EnchantmentInstance{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type identifier of this enchantment instance.
|
||||
* Returns the runtime type identifier of this enchantment instance.
|
||||
* WARNING: DO NOT STORE THIS IDENTIFIER - IT MAY CHANGE AFTER SERVER RESTART
|
||||
*/
|
||||
public function getId() : int{
|
||||
return $this->enchantment->getId();
|
||||
public function getRuntimeId() : int{
|
||||
return $this->enchantment->getRuntimeId();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,8 +38,8 @@ class ProtectionEnchantment extends Enchantment{
|
||||
*
|
||||
* @param int[]|null $applicableDamageTypes EntityDamageEvent::CAUSE_* constants which this enchantment type applies to, or null if it applies to all types of damage.
|
||||
*/
|
||||
public function __construct(int $id, string $name, int $rarity, int $primaryItemFlags, int $secondaryItemFlags, int $maxLevel, float $typeModifier, ?array $applicableDamageTypes){
|
||||
parent::__construct($id, $name, $rarity, $primaryItemFlags, $secondaryItemFlags, $maxLevel);
|
||||
public function __construct(int $internalRuntimeId, string $name, int $rarity, int $primaryItemFlags, int $secondaryItemFlags, int $maxLevel, float $typeModifier, ?array $applicableDamageTypes){
|
||||
parent::__construct($internalRuntimeId, $name, $rarity, $primaryItemFlags, $secondaryItemFlags, $maxLevel);
|
||||
|
||||
$this->typeModifier = $typeModifier;
|
||||
if($applicableDamageTypes !== null){
|
||||
|
@ -25,7 +25,6 @@ namespace pocketmine\item\enchantment;
|
||||
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\utils\RegistryTrait;
|
||||
use function array_key_exists;
|
||||
|
||||
/**
|
||||
* This doc-block is generated automatically, do not modify it manually.
|
||||
@ -55,12 +54,6 @@ use function array_key_exists;
|
||||
final class VanillaEnchantments{
|
||||
use RegistryTrait;
|
||||
|
||||
/**
|
||||
* @var Enchantment[]
|
||||
* @phpstan-var array<int, Enchantment>
|
||||
*/
|
||||
private static $mcpeIdMap = [];
|
||||
|
||||
protected static function setup() : void{
|
||||
self::register("PROTECTION", new ProtectionEnchantment(EnchantmentIds::PROTECTION, "%enchantment.protect.all", Rarity::COMMON, ItemFlags::ARMOR, ItemFlags::NONE, 4, 0.75, null));
|
||||
self::register("FIRE_PROTECTION", new ProtectionEnchantment(EnchantmentIds::FIRE_PROTECTION, "%enchantment.protect.fire", Rarity::UNCOMMON, ItemFlags::ARMOR, ItemFlags::NONE, 4, 1.25, [
|
||||
@ -103,17 +96,7 @@ final class VanillaEnchantments{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
38
tests/phpunit/data/bedrock/EnchantmentIdMapTest.php
Normal file
38
tests/phpunit/data/bedrock/EnchantmentIdMapTest.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\bedrock;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||
|
||||
class EnchantmentIdMapTest extends TestCase{
|
||||
|
||||
public function testAllEnchantsMapped() : void{
|
||||
foreach(VanillaEnchantments::getAll() as $enchantment){
|
||||
$id = EnchantmentIdMap::getInstance()->toId($enchantment);
|
||||
$enchantment2 = EnchantmentIdMap::getInstance()->fromId($id);
|
||||
self::assertTrue($enchantment === $enchantment2);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user