Remove circular dependency between Item and NBT modules (#121)

This commit is contained in:
Dylan K. Taylor 2016-11-25 10:17:50 +00:00 committed by GitHub
parent a0111d04ee
commit e51a2725de
7 changed files with 68 additions and 64 deletions

View File

@ -277,9 +277,9 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
if($item["Slot"] >= 0 and $item["Slot"] < 9){ //Hotbar
$this->inventory->setHotbarSlotIndex($item["Slot"], isset($item["TrueSlot"]) ? $item["TrueSlot"] : -1);
}elseif($item["Slot"] >= 100 and $item["Slot"] < 104){ //Armor
$this->inventory->setItem($this->inventory->getSize() + $item["Slot"] - 100, NBT::getItemHelper($item));
$this->inventory->setItem($this->inventory->getSize() + $item["Slot"] - 100, ItemItem::nbtDeserialize($item));
}else{
$this->inventory->setItem($item["Slot"] - 9, NBT::getItemHelper($item));
$this->inventory->setItem($item["Slot"] - 9, ItemItem::nbtDeserialize($item));
}
}
}
@ -407,7 +407,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
if($hotbarSlot !== -1){
$item = $this->inventory->getItem($hotbarSlot);
if($item->getId() !== 0 and $item->getCount() > 0){
$tag = NBT::putItemHelper($item, $slot);
$tag = $item->nbtSerialize($slot);
$tag->TrueSlot = new ByteTag("TrueSlot", $hotbarSlot);
$this->namedtag->Inventory[$slot] = $tag;
@ -429,14 +429,14 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
//$slotCount = (($this instanceof Player and ($this->gamemode & 0x01) === 1) ? Player::CREATIVE_SLOTS : Player::SURVIVAL_SLOTS) + 9;
for($slot = 9; $slot < $slotCount; ++$slot){
$item = $this->inventory->getItem($slot - 9);
$this->namedtag->Inventory[$slot] = NBT::putItemHelper($item, $slot);
$this->namedtag->Inventory[$slot] = $item->nbtSerialize($slot);
}
//Armor
for($slot = 100; $slot < 104; ++$slot){
$item = $this->inventory->getItem($this->inventory->getSize() + $slot - 100);
if($item instanceof ItemItem and $item->getId() !== ItemItem::AIR){
$this->namedtag->Inventory[$slot] = NBT::putItemHelper($item, $slot);
$this->namedtag->Inventory[$slot] = $item->nbtSerialize($slot);
}
}
}

View File

@ -75,7 +75,7 @@ class Item extends Entity{
assert($this->namedtag->Item instanceof CompoundTag);
$this->item = NBT::getItemHelper($this->namedtag->Item);
$this->item = ItemItem::nbtDeserialize($this->namedtag->Item);
$this->server->getPluginManager()->callEvent(new ItemSpawnEvent($this));
@ -160,7 +160,7 @@ class Item extends Entity{
public function saveNBT(){
parent::saveNBT();
$this->namedtag->Item = NBT::putItemHelper($this->item);
$this->namedtag->Item = $this->item->nbtSerialize();
$this->namedtag->Health = new ShortTag("Health", $this->getHealth());
$this->namedtag->Age = new ShortTag("Age", $this->age);
$this->namedtag->PickupDelay = new ShortTag("PickupDelay", $this->pickupDelay);

View File

@ -30,6 +30,7 @@ use pocketmine\inventory\Fuel;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\level\Level;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\ShortTag;
@ -770,4 +771,59 @@ class Item implements ItemIds, \JsonSerializable{
];
}
/**
* Serializes the item to an NBT CompoundTag
*
* @param int $slot optional, the inventory slot of the item
*
* @return CompoundTag
*/
public function nbtSerialize(int $slot = -1) : CompoundTag{
$tag = new CompoundTag(null, [
"id" => new ShortTag("id", $this->id),
"Count" => new ByteTag("Count", $this->count ?? -1),
"Damage" => new ShortTag("Damage", $this->meta),
]);
if($this->hasCompoundTag()){
$tag->tag = clone $this->getNamedTag();
$tag->tag->setName("tag");
}
if($slot !== -1){
$tag->Slot = new ByteTag("Slot", $slot);
}
return $tag;
}
/**
* Deserializes an Item from an NBT CompoundTag
*
* @param CompoundTag $tag
*
* @return Item
*/
public static function nbtDeserialize(CompoundTag $tag) : Item{
if(!isset($tag->id) or !isset($tag->Count)){
return Item::get(0);
}
if($tag->id instanceof ShortTag){
$item = Item::get($tag->id->getValue(), !isset($tag->Damage) ? 0 : $tag->Damage->getValue(), $tag->Count->getValue());
}elseif($tag->id instanceof StringTag){ //PC item save format
$item = Item::fromString($tag->id->getValue());
$item->setDamage(!isset($tag->Damage) ? 0 : $tag->Damage->getValue());
$item->setCount($tag->Count->getValue());
}else{
throw new \InvalidArgumentException("Item CompoundTag ID must be an instance of StringTag or ShortTag, " . get_class($tag->id) . " given");
}
if(isset($tag->tag) and $tag->tag instanceof CompoundTag){
$item->setNamedTag($tag->tag);
}
return $item;
}
}

View File

@ -1454,7 +1454,7 @@ class Level implements ChunkManager, Metadatable{
*/
public function dropItem(Vector3 $source, Item $item, Vector3 $motion = null, int $delay = 10){
$motion = $motion === null ? new Vector3(lcg_value() * 0.2 - 0.1, 0.2, lcg_value() * 0.2 - 0.1) : $motion;
$itemTag = NBT::putItemHelper($item);
$itemTag = $item->nbtSerialize();
$itemTag->setName("Item");
if($item->getId() > 0 and $item->getCount() > 0){

View File

@ -24,7 +24,6 @@
*/
namespace pocketmine\nbt;
use pocketmine\item\Item;
use pocketmine\nbt\tag\ByteArrayTag;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
@ -73,57 +72,6 @@ class NBT{
public $endianness;
private $data;
/**
* @param Item $item
* @param int $slot
* @return CompoundTag
*/
public static function putItemHelper(Item $item, $slot = null){
$tag = new CompoundTag(null, [
"id" => new ShortTag("id", $item->getId()),
"Count" => new ByteTag("Count", $item->getCount()),
"Damage" => new ShortTag("Damage", $item->getDamage())
]);
if($slot !== null){
$tag->Slot = new ByteTag("Slot", (int) $slot);
}
if($item->hasCompoundTag()){
$tag->tag = clone $item->getNamedTag();
$tag->tag->setName("tag");
}
return $tag;
}
/**
* @param CompoundTag $tag
* @return Item
*/
public static function getItemHelper(CompoundTag $tag){
if(!isset($tag->id) or !isset($tag->Count)){
return Item::get(0);
}
if($tag->id instanceof ShortTag){
$item = Item::get($tag->id->getValue(), !isset($tag->Damage) ? 0 : $tag->Damage->getValue(), $tag->Count->getValue());
}elseif($tag->id instanceof StringTag){ //PC item save format
$item = Item::fromString($tag->id->getValue());
$item->setDamage(!isset($tag->Damage) ? 0 : $tag->Damage->getValue());
$item->setCount($tag->Count->getValue());
}else{
throw new \InvalidArgumentException("Item CompoundTag ID must be an instance of StringTag or ShortTag, " . get_class($tag->id) . " given");
}
if(isset($tag->tag) and $tag->tag instanceof CompoundTag){
$item->setNamedTag($tag->tag);
}
return $item;
}
public static function matchList(ListTag $tag1, ListTag $tag2){
if($tag1->getName() !== $tag2->getName() or $tag1->getCount() !== $tag2->getCount()){
return false;

View File

@ -109,7 +109,7 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{
if($i < 0){
return Item::get(Item::AIR, 0, 0);
}else{
return NBT::getItemHelper($this->namedtag->Items[$i]);
return Item::nbtDeserialize($this->namedtag->Items[$i]);
}
}
@ -124,7 +124,7 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{
public function setItem($index, Item $item){
$i = $this->getSlotIndex($index);
$d = NBT::putItemHelper($item, $index);
$d = $item->nbtSerialize($index);
if($item->getId() === Item::AIR or $item->getCount() <= 0){
if($i >= 0){

View File

@ -138,7 +138,7 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{
if($i < 0){
return Item::get(Item::AIR, 0, 0);
}else{
return NBT::getItemHelper($this->namedtag->Items[$i]);
return Item::nbtDeserialize($this->namedtag->Items[$i]);
}
}
@ -153,7 +153,7 @@ class Furnace extends Spawnable implements InventoryHolder, Container, Nameable{
public function setItem($index, Item $item){
$i = $this->getSlotIndex($index);
$d = NBT::putItemHelper($item, $index);
$d = $item->nbtSerialize($index);
if($item->getId() === Item::AIR or $item->getCount() <= 0){
if($i >= 0){