mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-16 10:49:10 +00:00
Added custom block data (example, chests), better deep checking of same NBT
This commit is contained in:
parent
e9c981b586
commit
696edfd31f
@ -1945,7 +1945,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
break;
|
||||
}
|
||||
}
|
||||
}elseif($item === null or $slot === -1 or !$item->equals($packet->item)){ // packet error or not implemented
|
||||
}elseif($item === null or $slot === -1 or !$item->deepEquals($packet->item)){ // packet error or not implemented
|
||||
$this->inventory->sendContents($this);
|
||||
break;
|
||||
}elseif($this->isCreative()){
|
||||
@ -1985,14 +1985,14 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
|
||||
break;
|
||||
}
|
||||
}elseif(!$this->inventory->getItemInHand()->equals($packet->item)){
|
||||
}elseif(!$this->inventory->getItemInHand()->deepEquals($packet->item)){
|
||||
$this->inventory->sendHeldItem($this);
|
||||
}else{
|
||||
$item = $this->inventory->getItemInHand();
|
||||
$oldItem = clone $item;
|
||||
//TODO: Implement adventure mode checks
|
||||
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this)){
|
||||
if(!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()){
|
||||
if(!$item->deepEquals($oldItem) or $item->getCount() !== $oldItem->getCount()){
|
||||
$this->inventory->setItemInHand($item, $this);
|
||||
$this->inventory->sendHeldItem($this->hasSpawned);
|
||||
}
|
||||
@ -2015,7 +2015,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
if($this->isCreative()){
|
||||
$item = $this->inventory->getItemInHand();
|
||||
}elseif(!$this->inventory->getItemInHand()->equals($packet->item)){
|
||||
}elseif(!$this->inventory->getItemInHand()->deepEquals($packet->item)){
|
||||
$this->inventory->sendHeldItem($this);
|
||||
break;
|
||||
}else{
|
||||
@ -2251,7 +2251,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
if($this->canInteract($vector->add(0.5, 0.5, 0.5), $this->isCreative() ? 13 : 6) and $this->level->useBreakOn($vector, $item, $this)){
|
||||
if($this->isSurvival()){
|
||||
if(!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()){
|
||||
if(!$item->deepEquals($oldItem) or $item->getCount() !== $oldItem->getCount()){
|
||||
$this->inventory->setItemInHand($item, $this);
|
||||
$this->inventory->sendHeldItem($this->hasSpawned);
|
||||
}
|
||||
@ -2610,7 +2610,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$slot = -1;
|
||||
$checkDamage = $ingredient->getDamage() === null ? false : true;
|
||||
foreach($this->inventory->getContents() as $index => $i){
|
||||
if($ingredient->equals($i, $checkDamage) and ($i->getCount() - $used[$index]) >= 1){
|
||||
if($ingredient->deepEquals($i, $checkDamage) and ($i->getCount() - $used[$index]) >= 1){
|
||||
$slot = $index;
|
||||
$used[$index]++;
|
||||
break;
|
||||
@ -2723,7 +2723,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
break;
|
||||
}
|
||||
|
||||
if($transaction->getSourceItem()->equals($transaction->getTargetItem()) and $transaction->getTargetItem()->getCount() === $transaction->getSourceItem()->getCount()){ //No changes!
|
||||
if($transaction->getSourceItem()->deepEquals($transaction->getTargetItem()) and $transaction->getTargetItem()->getCount() === $transaction->getSourceItem()->getCount()){ //No changes!
|
||||
//No changes, just a local inventory update sent by the server
|
||||
break;
|
||||
}
|
||||
|
@ -82,6 +82,12 @@ class BurningFurnace extends Solid{
|
||||
$nbt->CustomName = new String("CustomName", $item->getCustomName());
|
||||
}
|
||||
|
||||
if($item->hasCustomBlockData()){
|
||||
foreach($item->getCustomBlockData() as $key => $v){
|
||||
$nbt->{$key} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
Tile::createTile("Furnace", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
|
||||
return true;
|
||||
|
@ -109,6 +109,12 @@ class Chest extends Transparent{
|
||||
$nbt->CustomName = new String("CustomName", $item->getCustomName());
|
||||
}
|
||||
|
||||
if($item->hasCustomBlockData()){
|
||||
foreach($item->getCustomBlockData() as $key => $v){
|
||||
$nbt->{$key} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
$tile = Tile::createTile("Chest", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
|
||||
if($chest instanceof TileChest and $tile instanceof TileChest){
|
||||
|
@ -52,6 +52,12 @@ class EnchantingTable extends Transparent{
|
||||
$nbt->CustomName = new String("CustomName", $item->getCustomName());
|
||||
}
|
||||
|
||||
if($item->hasCustomBlockData()){
|
||||
foreach($item->getCustomBlockData() as $key => $v){
|
||||
$nbt->{$key} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
|
||||
return true;
|
||||
|
@ -70,6 +70,10 @@ class Item extends Entity{
|
||||
if(isset($this->namedtag->Thrower)){
|
||||
$this->thrower = $this->namedtag["Thrower"];
|
||||
}
|
||||
if(!isset($this->namedtag->Item)){
|
||||
$this->close();
|
||||
return;
|
||||
}
|
||||
$this->item = NBT::getItemHelper($this->namedtag->Item);
|
||||
|
||||
|
||||
|
@ -98,7 +98,7 @@ class SimpleTransactionGroup implements TransactionGroup{
|
||||
}
|
||||
$checkSourceItem = $ts->getInventory()->getItem($ts->getSlot());
|
||||
$sourceItem = $ts->getSourceItem();
|
||||
if(!$checkSourceItem->equals($sourceItem) or $sourceItem->getCount() !== $checkSourceItem->getCount()){
|
||||
if(!$checkSourceItem->deepEquals($sourceItem) or $sourceItem->getCount() !== $checkSourceItem->getCount()){
|
||||
return false;
|
||||
}
|
||||
if($sourceItem->getId() !== Item::AIR){
|
||||
@ -108,7 +108,7 @@ class SimpleTransactionGroup implements TransactionGroup{
|
||||
|
||||
foreach($needItems as $i => $needItem){
|
||||
foreach($haveItems as $j => $haveItem){
|
||||
if($needItem->equals($haveItem)){
|
||||
if($needItem->deepEquals($haveItem)){
|
||||
$amount = min($needItem->getCount(), $haveItem->getCount());
|
||||
$needItem->setCount($needItem->getCount() - $amount);
|
||||
$haveItem->setCount($haveItem->getCount() - $amount);
|
||||
|
@ -968,6 +968,62 @@ class Item{
|
||||
return $this->tags !== "" and $this->tags !== null;
|
||||
}
|
||||
|
||||
public function hasCustomBlockData(){
|
||||
if(!$this->hasCompoundTag()){
|
||||
return false;
|
||||
}
|
||||
|
||||
$tag = $this->getNamedTag();
|
||||
if(isset($tag->BlockEntityTag) and $tag->BlockEntityTag instanceof Compound){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function clearCustomBlockData(){
|
||||
if(!$this->hasCompoundTag()){
|
||||
return $this;
|
||||
}
|
||||
$tag = $this->getNamedTag();
|
||||
|
||||
if(isset($tag->BlockEntityTag) and $tag->BlockEntityTag instanceof Compound){
|
||||
unset($tag->display->BlockEntityTag);
|
||||
$this->setNamedTag($tag);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCustomBlockData(Compound $compound){
|
||||
$tags = clone $compound;
|
||||
$tags->setName("BlockEntityTag");
|
||||
|
||||
if(!$this->hasCompoundTag()){
|
||||
$tag = new Compound("", []);
|
||||
}else{
|
||||
$tag = $this->getNamedTag();
|
||||
}
|
||||
|
||||
$tag->BlockEntityTag = $tags;
|
||||
$this->setNamedTag($tag);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCustomBlockData(){
|
||||
if(!$this->hasCompoundTag()){
|
||||
return null;
|
||||
}
|
||||
|
||||
$tag = $this->getNamedTag();
|
||||
if(isset($tag->BlockEntityTag) and $tag->BlockEntityTag instanceof Compound){
|
||||
return $tag->BlockEntityTag;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function hasCustomName(){
|
||||
if(!$this->hasCompoundTag()){
|
||||
return false;
|
||||
@ -1191,4 +1247,14 @@ class Item{
|
||||
return $this->id === $item->getId() and ($checkDamage === false or $this->getDamage() === $item->getDamage()) and ($checkCompound === false or $this->getCompoundTag() === $item->getCompoundTag());
|
||||
}
|
||||
|
||||
public final function deepEquals(Item $item){
|
||||
if($item->equals($item)){
|
||||
return true;
|
||||
}elseif($item->hasCompoundTag() or $this->hasCompoundTag()){
|
||||
return NBT::matchTree($this->getNamedTag(), $item->getNamedTag());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1727,7 +1727,8 @@ class Level implements ChunkManager, Metadatable{
|
||||
}
|
||||
|
||||
if($hand->getId() === Item::SIGN_POST or $hand->getId() === Item::WALL_SIGN){
|
||||
$tile = Tile::createTile("Sign", $this->getChunk($block->x >> 4, $block->z >> 4), new Compound("", [
|
||||
|
||||
$nbt = new Compound("", [
|
||||
"id" => new String("id", Tile::SIGN),
|
||||
"x" => new Int("x", $block->x),
|
||||
"y" => new Int("y", $block->y),
|
||||
@ -1736,10 +1737,19 @@ class Level implements ChunkManager, Metadatable{
|
||||
"Text2" => new String("Text2", ""),
|
||||
"Text3" => new String("Text3", ""),
|
||||
"Text4" => new String("Text4", "")
|
||||
]));
|
||||
]);
|
||||
|
||||
if($player !== null){
|
||||
$tile->namedtag->Creator = new String("Creator", $player->getRawUniqueId());
|
||||
$nbt->Creator = new String("Creator", $player->getRawUniqueId());
|
||||
}
|
||||
|
||||
if($item->hasCustomBlockData()){
|
||||
foreach($item->getCustomBlockData() as $key => $v){
|
||||
$nbt->{$key} = $v;
|
||||
}
|
||||
}
|
||||
|
||||
Tile::createTile("Sign", $this->getChunk($block->x >> 4, $block->z >> 4), $nbt);
|
||||
}
|
||||
$item->setCount($item->getCount() - 1);
|
||||
if($item->getCount() <= 0){
|
||||
|
@ -104,11 +104,11 @@ class NBT{
|
||||
* @return Item
|
||||
*/
|
||||
public static function getItemHelper(Compound $tag){
|
||||
if(!isset($tag->id) or !isset($tag->Damage) or !isset($tag->Count)){
|
||||
if(!isset($tag->id) or !isset($tag->Count)){
|
||||
return Item::get(0);
|
||||
}
|
||||
|
||||
$item = Item::get($tag->id->getValue(), $tag->Damage->getValue(), $tag->Count->getValue());
|
||||
$item = Item::get($tag->id->getValue(), !isset($tag->Damage) ? 0 : $tag->Damage->getValue(), $tag->Count->getValue());
|
||||
|
||||
if(isset($tag->tag) and $tag->tag instanceof Compound){
|
||||
$item->setNamedTag($tag->tag);
|
||||
@ -117,6 +117,70 @@ class NBT{
|
||||
return $item;
|
||||
}
|
||||
|
||||
public static function matchList(Enum $tag1, Enum $tag2){
|
||||
if($tag1->getName() !== $tag2->getName() or $tag1->getCount() !== $tag2->getCount()){
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach($tag1 as $k => $v){
|
||||
if(!($v instanceof Tag)){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!isset($tag2->{$k}) or !($tag2->{$k} instanceof $v)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($v instanceof Compound){
|
||||
if(!self::matchTree($v, $tag2->{$k})){
|
||||
return false;
|
||||
}
|
||||
}elseif($v instanceof Enum){
|
||||
if(!self::matchList($v, $tag2->{$k})){
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if($v->getValue() !== $tag2->{$k}->getValue()){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function matchTree(Compound $tag1, Compound $tag2){
|
||||
if($tag1->getName() !== $tag2->getName() or $tag1->getCount() !== $tag2->getCount()){
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach($tag1 as $k => $v){
|
||||
if(!($v instanceof Tag)){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!isset($tag2->{$k}) or !($tag2->{$k} instanceof $v)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($v instanceof Compound){
|
||||
if(!self::matchTree($v, $tag2->{$k})){
|
||||
return false;
|
||||
}
|
||||
}elseif($v instanceof Enum){
|
||||
if(!self::matchList($v, $tag2->{$k})){
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if($v->getValue() !== $tag2->{$k}->getValue()){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get($len){
|
||||
if($len < 0){
|
||||
$this->offset = strlen($this->buffer) - 1;
|
||||
|
@ -47,7 +47,7 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{
|
||||
$this->inventory = new ChestInventory($this);
|
||||
|
||||
if(!isset($this->namedtag->Items) or !($this->namedtag->Items instanceof Enum)){
|
||||
$this->namedtag->Items = new Enum("Inventory", []);
|
||||
$this->namedtag->Items = new Enum("Items", []);
|
||||
$this->namedtag->Items->setTagType(NBT::TAG_Compound);
|
||||
}
|
||||
|
||||
@ -91,8 +91,8 @@ class Chest extends Spawnable implements InventoryHolder, Container, Nameable{
|
||||
*/
|
||||
protected function getSlotIndex($index){
|
||||
foreach($this->namedtag->Items as $i => $slot){
|
||||
if($slot["Slot"] === $index){
|
||||
return $i;
|
||||
if((int) $slot["Slot"] === (int) $index){
|
||||
return (int) $i;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user