Enchantment: Split up enchantment type data and enchantment instance data (#1825)

* Enchantment: Split enchantment type data from instance data
This commit splits enchantments into (effectively) enchantment TYPES vs enchantment INSTANCES.

When applying an enchantment to an item, it only needs to know 2 things:
1. the enchantment ID (identifier) which is used to identify the TYPE
2. the enchantment LEVEL which is used to modify the enchantment's power IN THIS INSTANCE.

Therefore, the LEVEL is not an immutable property. However, all other properties of the currently-named "Enchantment" class are immutable type properties.
Currently, when applying an enchantment to an item, a copy of the enchantment object is created from the registry, and returned. This copies all of the properties contained by the type, which is obviously sub optimal.
This commit is contained in:
Dylan K. Taylor 2017-12-21 12:40:33 +00:00 committed by GitHub
parent 1b4b832c8c
commit 0e538ee51d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 38 deletions

View File

@ -27,6 +27,7 @@ use pocketmine\command\CommandSender;
use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\event\TranslationContainer;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\enchantment\EnchantmentInstance;
use pocketmine\utils\TextFormat;
class EnchantCommand extends VanillaCommand{
@ -74,9 +75,7 @@ class EnchantCommand extends VanillaCommand{
return true;
}
$enchantment->setLevel((int) ($args[2] ?? 1));
$item->addEnchantment($enchantment);
$item->addEnchantment(new EnchantmentInstance($enchantment, (int) ($args[2] ?? 1)));
$player->getInventory()->setItemInHand($item);

View File

@ -31,6 +31,7 @@ use pocketmine\block\BlockFactory;
use pocketmine\block\BlockToolType;
use pocketmine\entity\Entity;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\enchantment\EnchantmentInstance;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\nbt\NBT;
@ -310,9 +311,9 @@ class Item implements ItemIds, \JsonSerializable{
/**
* @param int $id
*
* @return Enchantment|null
* @return EnchantmentInstance|null
*/
public function getEnchantment(int $id) : ?Enchantment{
public function getEnchantment(int $id) : ?EnchantmentInstance{
$ench = $this->getNamedTagEntry(self::TAG_ENCH);
if(!($ench instanceof ListTag)){
return null;
@ -323,8 +324,7 @@ class Item implements ItemIds, \JsonSerializable{
if($entry->getShort("id") === $id){
$e = Enchantment::getEnchantment($entry->getShort("id"));
if($e !== null){
$e->setLevel($entry->getShort("lvl"));
return $e;
return new EnchantmentInstance($e, $entry->getShort("lvl"));
}
}
}
@ -358,9 +358,9 @@ class Item implements ItemIds, \JsonSerializable{
}
/**
* @param Enchantment $enchantment
* @param EnchantmentInstance $enchantment
*/
public function addEnchantment(Enchantment $enchantment) : void{
public function addEnchantment(EnchantmentInstance $enchantment) : void{
$found = false;
$ench = $this->getNamedTagEntry(self::TAG_ENCH);
@ -391,10 +391,10 @@ class Item implements ItemIds, \JsonSerializable{
}
/**
* @return Enchantment[]
* @return EnchantmentInstance[]
*/
public function getEnchantments() : array{
/** @var Enchantment[] $enchantments */
/** @var EnchantmentInstance[] $enchantments */
$enchantments = [];
$ench = $this->getNamedTagEntry(self::TAG_ENCH);
@ -403,8 +403,7 @@ class Item implements ItemIds, \JsonSerializable{
foreach($ench as $entry){
$e = Enchantment::getEnchantment($entry->getShort("id"));
if($e !== null){
$e->setLevel($entry->getShort("lvl"));
$enchantments[] = $e;
$enchantments[] = new EnchantmentInstance($e, $entry->getShort("lvl"));
}
}
}

View File

@ -23,7 +23,9 @@ declare(strict_types=1);
namespace pocketmine\item\enchantment;
/**
* Manages enchantment type data.
*/
class Enchantment{
public const PROTECTION = 0;
@ -110,7 +112,7 @@ class Enchantment{
*/
public static function getEnchantment(int $id){
if(isset(self::$enchantments[$id])){
return clone self::$enchantments[$id];
return self::$enchantments[$id];
}
return null;
}
@ -129,8 +131,6 @@ class Enchantment{
/** @var int */
private $id;
/** @var int */
private $level = 1;
/** @var string */
private $name;
/** @var int */
@ -204,25 +204,4 @@ class Enchantment{
public function hasSlot(int $slot) : bool{
return ($this->slot & $slot) > 0;
}
/**
* Returns the level of the enchantment.
* @return int
*/
public function getLevel() : int{
return $this->level;
}
/**
* Sets the level of the enchantment.
* @param int $level
*
* @return $this
*/
public function setLevel(int $level){
$this->level = $level;
return $this;
}
}

View File

@ -0,0 +1,81 @@
<?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\item\enchantment;
/**
* Container for enchantment data applied to items.
*/
class EnchantmentInstance{
/** @var Enchantment */
private $enchantment;
/** @var int */
private $level;
/**
* EnchantmentInstance constructor.
*
* @param Enchantment $enchantment Enchantment type
* @param int $level Level of enchantment
*/
public function __construct(Enchantment $enchantment, int $level = 1){
$this->enchantment = $enchantment;
$this->level = $level;
}
/**
* Returns the type of this enchantment.
* @return Enchantment
*/
public function getType() : Enchantment{
return $this->enchantment;
}
/**
* Returns the type identifier of this enchantment instance.
* @return int
*/
public function getId() : int{
return $this->enchantment->getId();
}
/**
* Returns the level of the enchantment.
* @return int
*/
public function getLevel() : int{
return $this->level;
}
/**
* Sets the level of the enchantment.
* @param int $level
*
* @return $this
*/
public function setLevel(int $level){
$this->level = $level;
return $this;
}
}