Some cleanup to item NBT handling

This commit is contained in:
Dylan K. Taylor 2017-10-16 10:15:41 +01:00
parent 97e2d64592
commit 8c6ab3e634

View File

@ -241,19 +241,11 @@ class Item implements ItemIds, \JsonSerializable{
* @return bool * @return bool
*/ */
public function hasCustomBlockData() : bool{ public function hasCustomBlockData() : bool{
$tag = $this->getNamedTag(); return $this->getNamedTagEntry("BlockEntityTag") instanceof CompoundTag;
return isset($tag->BlockEntityTag) and $tag->BlockEntityTag instanceof CompoundTag;
} }
public function clearCustomBlockData(){ public function clearCustomBlockData(){
$tag = $this->getNamedTag(); $this->removeNamedTagEntry("BlockEntityTag");
if(isset($tag->BlockEntityTag) and $tag->BlockEntityTag instanceof CompoundTag){
unset($tag->BlockEntityTag);
$this->setNamedTag($tag);
}
return $this; return $this;
} }
@ -265,10 +257,7 @@ class Item implements ItemIds, \JsonSerializable{
public function setCustomBlockData(CompoundTag $compound){ public function setCustomBlockData(CompoundTag $compound){
$tags = clone $compound; $tags = clone $compound;
$tags->setName("BlockEntityTag"); $tags->setName("BlockEntityTag");
$this->setNamedTagEntry($tags);
$tag = $this->getNamedTag();
$tag->BlockEntityTag = $tags;
$this->setNamedTag($tag);
return $this; return $this;
} }
@ -277,21 +266,15 @@ class Item implements ItemIds, \JsonSerializable{
* @return CompoundTag|null * @return CompoundTag|null
*/ */
public function getCustomBlockData(){ public function getCustomBlockData(){
$tag = $this->getNamedTag(); $tag = $this->getNamedTagEntry("BlockEntityTag");
if(isset($tag->BlockEntityTag) and $tag->BlockEntityTag instanceof CompoundTag){ return $tag instanceof CompoundTag ? $tag : null;
return $tag->BlockEntityTag;
}
return null;
} }
/** /**
* @return bool * @return bool
*/ */
public function hasEnchantments() : bool{ public function hasEnchantments() : bool{
$tag = $this->getNamedTag(); return $this->getNamedTagEntry("ench") instanceof ListTag;
return isset($tag->ench) and $tag->ench instanceof ListTag;
} }
/** /**
@ -301,15 +284,15 @@ class Item implements ItemIds, \JsonSerializable{
* @return bool * @return bool
*/ */
public function hasEnchantment(int $id, int $level = -1) : bool{ public function hasEnchantment(int $id, int $level = -1) : bool{
if(!$this->hasEnchantments()){ $ench = $this->getNamedTagEntry("ench");
if(!($ench instanceof ListTag)){
return false; return false;
} }
foreach($this->getNamedTag()->ench as $entry){ /** @var CompoundTag $entry */
if($entry["id"] === $id){ foreach($ench as $entry){
if($level === -1 or $entry["lvl"] === $level){ if($entry->getShort("id") === $id and ($level === -1 or $entry->getShort("lvl") === $level)){
return true; return true;
}
} }
} }
@ -322,15 +305,17 @@ class Item implements ItemIds, \JsonSerializable{
* @return Enchantment|null * @return Enchantment|null
*/ */
public function getEnchantment(int $id){ public function getEnchantment(int $id){
if(!$this->hasEnchantments()){ $ench = $this->getNamedTagEntry("ench");
if(!($ench instanceof ListTag)){
return null; return null;
} }
foreach($this->getNamedTag()->ench as $entry){ /** @var CompoundTag $entry */
if($entry["id"] === $id){ foreach($ench as $entry){
$e = Enchantment::getEnchantment($entry["id"]); if($entry->getShort("id") === $id){
$e = Enchantment::getEnchantment($entry->getShort("id"));
if($e !== null){ if($e !== null){
$e->setLevel($entry["lvl"]); $e->setLevel($entry->getShort("lvl"));
return $e; return $e;
} }
} }
@ -344,46 +329,42 @@ class Item implements ItemIds, \JsonSerializable{
* @param int $level * @param int $level
*/ */
public function removeEnchantment(int $id, int $level = -1){ public function removeEnchantment(int $id, int $level = -1){
if(!$this->hasEnchantments()){ $ench = $this->getNamedTagEntry("ench");
if(!($ench instanceof ListTag)){
return; return;
} }
$tag = $this->getNamedTag(); /** @var CompoundTag $entry */
foreach($tag->ench as $k => $entry){ foreach($ench as $k => $entry){
if($entry["id"] === $id){ if($entry->getShort("id") === $id and ($level === -1 or $entry->getShort("lvl") === $level)){
if($level === -1 or $entry["lvl"] === $level){ unset($ench[$k]);
unset($tag->ench[$k]); break;
break;
}
} }
} }
$this->setNamedTag($tag);
$this->setNamedTagEntry($ench);
} }
public function removeEnchantments(){ public function removeEnchantments(){
if($this->hasEnchantments()){ $this->removeNamedTagEntry("ench");
$tag = $this->getNamedTag();
unset($tag->ench);
$this->setNamedTag($tag);
}
} }
/** /**
* @param Enchantment $ench * @param Enchantment $enchantment
*/ */
public function addEnchantment(Enchantment $ench){ public function addEnchantment(Enchantment $enchantment){
$tag = $this->getNamedTag();
$found = false; $found = false;
if(!isset($tag->ench)){ $ench = $this->getNamedTagEntry("ench");
$tag->ench = new ListTag("ench", [], NBT::TAG_Compound); if(!($ench instanceof ListTag)){
$ench = new ListTag("ench", [], NBT::TAG_Compound);
}else{ }else{
foreach($tag->ench as $k => $entry){ /** @var CompoundTag $entry */
if($entry["id"] === $ench->getId()){ foreach($ench as $k => $entry){
$tag->ench->{$k} = new CompoundTag("", [ if($entry->getShort("id") === $enchantment->getId()){
new ShortTag("id", $ench->getId()), $ench->{$k} = new CompoundTag("", [
new ShortTag("lvl", $ench->getLevel()) new ShortTag("id", $enchantment->getId()),
new ShortTag("lvl", $enchantment->getLevel())
]); ]);
$found = true; $found = true;
break; break;
@ -392,26 +373,29 @@ class Item implements ItemIds, \JsonSerializable{
} }
if(!$found){ if(!$found){
$tag->ench->{count($tag->ench)} = new CompoundTag("", [ $ench->{count($ench)} = new CompoundTag("", [
new ShortTag("id", $ench->getId()), new ShortTag("id", $enchantment->getId()),
new ShortTag("lvl", $ench->getLevel()) new ShortTag("lvl", $enchantment->getLevel())
]); ]);
} }
$this->setNamedTag($tag); $this->setNamedTagEntry($ench);
} }
/** /**
* @return Enchantment[] * @return Enchantment[]
*/ */
public function getEnchantments() : array{ public function getEnchantments() : array{
/** @var Enchantment[] $enchantments */
$enchantments = []; $enchantments = [];
if($this->hasEnchantments()){ $ench = $this->getNamedTagEntry("ench");
foreach($this->getNamedTag()->ench as $entry){ if($ench instanceof ListTag){
$e = Enchantment::getEnchantment($entry["id"]); /** @var CompoundTag $entry */
foreach($ench as $entry){
$e = Enchantment::getEnchantment($entry->getShort("id"));
if($e !== null){ if($e !== null){
$e->setLevel($entry["lvl"]); $e->setLevel($entry->getShort("lvl"));
$enchantments[] = $e; $enchantments[] = $e;
} }
} }
@ -424,12 +408,9 @@ class Item implements ItemIds, \JsonSerializable{
* @return bool * @return bool
*/ */
public function hasCustomName() : bool{ public function hasCustomName() : bool{
$tag = $this->getNamedTag(); $display = $this->getNamedTagEntry("display");
if(isset($tag->display)){ if($display instanceof CompoundTag){
$tag = $tag->display; return $display->hasTag("Name");
if($tag instanceof CompoundTag and isset($tag->Name) and $tag->Name instanceof StringTag){
return true;
}
} }
return false; return false;
@ -439,12 +420,9 @@ class Item implements ItemIds, \JsonSerializable{
* @return string * @return string
*/ */
public function getCustomName() : string{ public function getCustomName() : string{
$tag = $this->getNamedTag(); $display = $this->getNamedTagEntry("display");
if(isset($tag->display)){ if($display instanceof CompoundTag){
$tag = $tag->display; return $display->getString("Name") ?? "";
if($tag instanceof CompoundTag and isset($tag->Name) and $tag->Name instanceof StringTag){
return $tag->Name->getValue();
}
} }
return ""; return "";
@ -460,16 +438,14 @@ class Item implements ItemIds, \JsonSerializable{
$this->clearCustomName(); $this->clearCustomName();
} }
$tag = $this->getNamedTag(); /** @var CompoundTag $display */
if(isset($tag->display) and $tag->display instanceof CompoundTag){ $display = $this->getNamedTagEntry("display");
$tag->display->Name = new StringTag("Name", $name); if(!($display instanceof CompoundTag)){
}else{ $display = new CompoundTag("display");
$tag->display = new CompoundTag("display", [
new StringTag("Name", $name)
]);
} }
$this->setCompoundTag($tag); $display->setString("Name", $name);
$this->setNamedTagEntry($display);
return $this; return $this;
} }
@ -478,30 +454,29 @@ class Item implements ItemIds, \JsonSerializable{
* @return $this * @return $this
*/ */
public function clearCustomName(){ public function clearCustomName(){
$tag = $this->getNamedTag(); $display = $this->getNamedTagEntry("display");
if($display instanceof CompoundTag){
$display->removeTag("Name");
if(isset($tag->display) and $tag->display instanceof CompoundTag){ if($display->getCount() === 0){
unset($tag->display->Name); $this->removeNamedTagEntry($display->getName());
if($tag->display->getCount() === 0){ }else{
unset($tag->display); $this->setNamedTagEntry($display);
} }
$this->setNamedTag($tag);
} }
return $this; return $this;
} }
/**
* @return string[]
*/
public function getLore() : array{ public function getLore() : array{
$tag = $this->getNamedTagEntry("display"); $display = $this->getNamedTagEntry("display");
if($tag instanceof CompoundTag and isset($tag->Lore) and $tag->Lore instanceof ListTag){ if($display instanceof CompoundTag and ($lore = $display->getListTag("Lore")) !== null){
$lines = []; return array_map(function(StringTag $tag) : string{
/** @var StringTag $line */ return $tag->getValue();
foreach($tag->Lore->getValue() as $line){ }, $lore->getValue());
$lines[] = $line->getValue();
}
return $lines;
} }
return []; return [];
@ -513,17 +488,16 @@ class Item implements ItemIds, \JsonSerializable{
* @return $this * @return $this
*/ */
public function setLore(array $lines){ public function setLore(array $lines){
$tag = $this->getNamedTag(); $display = $this->getNamedTagEntry("display");
if(!isset($tag->display)){ if(!($display instanceof CompoundTag)){
$tag->display = new CompoundTag("display", []); $display = new CompoundTag("display", []);
}
$tag->display->Lore = new ListTag("Lore", [], NBT::TAG_String);
$count = 0;
foreach($lines as $line){
$tag->display->Lore[$count++] = new StringTag("", $line);
} }
$this->setNamedTag($tag); $display->setTag(new ListTag("Lore", array_map(function(string $str) : StringTag{
return new StringTag("", $str);
}, $lines), NBT::TAG_String));
$this->setNamedTagEntry($display);
return $this; return $this;
} }
@ -944,22 +918,23 @@ class Item implements ItemIds, \JsonSerializable{
* @return CompoundTag * @return CompoundTag
*/ */
public function nbtSerialize(int $slot = -1, string $tagName = "") : CompoundTag{ public function nbtSerialize(int $slot = -1, string $tagName = "") : CompoundTag{
$tag = new CompoundTag($tagName, [ $result = new CompoundTag($tagName, [
new ShortTag("id", Binary::signShort($this->id)), new ShortTag("id", Binary::signShort($this->id)),
new ByteTag("Count", Binary::signByte($this->count)), new ByteTag("Count", Binary::signByte($this->count)),
new ShortTag("Damage", $this->meta), new ShortTag("Damage", $this->meta)
]); ]);
if($this->hasCompoundTag()){ if($this->hasCompoundTag()){
$tag->tag = clone $this->getNamedTag(); $itemNBT = clone $this->getNamedTag();
$tag->tag->setName("tag"); $itemNBT->setName("tag");
$result->setTag($itemNBT);
} }
if($slot !== -1){ if($slot !== -1){
$tag->Slot = new ByteTag("Slot", $slot); $result->setByte("Slot", $slot);
} }
return $tag; return $result;
} }
/** /**
@ -970,26 +945,28 @@ class Item implements ItemIds, \JsonSerializable{
* @return Item * @return Item
*/ */
public static function nbtDeserialize(CompoundTag $tag) : Item{ public static function nbtDeserialize(CompoundTag $tag) : Item{
if(!isset($tag->id) or !isset($tag->Count)){ if(!$tag->hasTag("id") or !$tag->hasTag("Count")){
return ItemFactory::get(0); return ItemFactory::get(0);
} }
$count = Binary::unsignByte($tag->Count->getValue()); $count = Binary::unsignByte($tag->getByte("Count"));
$meta = isset($tag->Damage) ? $tag->Damage->getValue() : 0; $meta = $tag->getShort("Damage") ?? 0;
if($tag->id instanceof ShortTag){ $idTag = $tag->getTag("id");
$item = ItemFactory::get(Binary::unsignShort($tag->id->getValue()), $meta, $count); if($idTag instanceof ShortTag){
}elseif($tag->id instanceof StringTag){ //PC item save format $item = ItemFactory::get(Binary::unsignShort($idTag->getValue()), $meta, $count);
$item = ItemFactory::fromString($tag->id->getValue()); }elseif($idTag instanceof StringTag){ //PC item save format
$item = ItemFactory::fromString($idTag->getValue());
$item->setDamage($meta); $item->setDamage($meta);
$item->setCount($count); $item->setCount($count);
}else{ }else{
throw new \InvalidArgumentException("Item CompoundTag ID must be an instance of StringTag or ShortTag, " . get_class($tag->id) . " given"); throw new \InvalidArgumentException("Item CompoundTag ID must be an instance of StringTag or ShortTag, " . get_class($idTag) . " given");
} }
if(isset($tag->tag) and $tag->tag instanceof CompoundTag){ $itemNBT = $tag->getCompoundTag("tag");
if($itemNBT instanceof CompoundTag){
/** @var CompoundTag $t */ /** @var CompoundTag $t */
$t = clone $tag->tag; $t = clone $itemNBT;
$t->setName(""); $t->setName("");
$item->setNamedTag($t); $item->setNamedTag($t);
} }