Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tile NBT usage enhancements #1259

Merged
merged 11 commits into from
Aug 6, 2017
Merged

Tile NBT usage enhancements #1259

merged 11 commits into from
Aug 6, 2017

Conversation

Muqsit
Copy link
Contributor

@Muqsit Muqsit commented Jul 30, 2017

Introduction

Relevant issues

It looks like for every time PocketMine needs to change the value of a tile's NBT tag, it creates a totally new NBT tag and assigns it a value.

/** @var \pocketmine\tile\Furnace $furnace */

//onUpdate()...
if($furnace->namedtag["BurnTime"] > 0){
    $furnace->namedtag["BurnTime"] = new ShortTag("BurnTime", ((int) $furnace->namedtag["BurnTime"]) - 1);
}

Its pointless. You can change the tag's value using Tag::setValue($value).
It also seems pointless to (mixed) cast every nbt tag. This can be avoided by using Tag::getValue().

//Before:
if($furnace->namedtag["BurnTime"] > 0){
    $furnace->namedtag["BurnTime"] = new ShortTag("BurnTime", ((int) $furnace->namedtag["BurnTime"]) - 1);
}

//After:
if($furnace->namedtag->BurnTime->getValue() > 0){
    $furnace->namedtag->BurnTime->setValue($furnace->namedtag->BurnTime->getValue() - 1);
}

Changes

API changes

This pull request goes hand in hand with #1116. You can still assign an index to a CompoundTag array, but it's going to be useless.
If you are modifying a tile, please use the new way which again, is what's explained in #1116.

//Do NOT:
$tileNBT = new CompoundTag("", [
    "x" => new IntTag("x", 100)
]);
var_dump((int) $tileNBT["x"]);

//Do:
$tileNBT = new CompoundTag("", [
    new IntTag("x", 100)
]);
var_dump($tileNBT->x->getValue());

"------------------------------"

//Do NOT:
$tileNBT["x"] = new IntTag("x", ((int) $tileNBT["x"]) + 10);

//Do:
$tileNBT->x->setValue($tileNBT->x->getValue() + 10);

Spawnable::getSpawnCompound() is no longer an abstract function and returns generic tile NBT.

Added abstract function addAdditionalSpawnData(CompoundTag $nbt) which is where all the tile-specific nbt tags are applied.

Behavioural changes

This can be considered a 'micro-optimization' since we aren't creating multiple new NBT tags every tick as seen in case of Furnace.

Backwards compatibility

This PR is backwards compatible.

Tests

Tests done:
Chest
Place a chest. Put some items in it. Close the chest. Restart the server. Open the chest. Works just like it should.

Enchanting Table:
Place an enchanting table. Open it. Close it. Restart the server. Open it. Close it. Works.

Flower Pot:
Place a flower pot. Add a flower (tried with cactus). Restart the server. Works.

Item Frame:
Place an item frame. Rotate item 45° (1 tap). Restart the server. Works.

Sign:
Place a sign. Fill up all four lines. Restart the server. Works.
Place a sign. Fill up the 2nd and 4th line. Restart the server. Works.

Skull:
Place a skull with rotation % 90 !== 0. Restart the server. Works.
Place a skull with rotation % 90 === 0. Restart the server. Works.

API Changes made after initial changes

Spawnable::getSpawnCompound() is now a final function. It will return the common NBT tag for tiles...

final public function getSpawnCompound() : CompoundTag{
    return new CompoundTag("", [
        $this->namedtag->id,
        $this->namedtag->x,
        $this->namedtag->y,
        $this->namedtag->z
    ]);
}

@@ -66,12 +65,12 @@ public function canAddItem(Item $item) : bool{
}

public function getItem() : Item{
return Item::get((int) ($this->namedtag["item"] ?? 0), (int) ($this->namedtag["mData"] ?? 0), 1);
return Item::get($this->namedtag->item->getValue(), $this->namedtag->mData->getValue(), 1);
Copy link
Contributor Author

@Muqsit Muqsit Jul 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case you were wondering why I did not check whether $this->namedtag->item or $this->namedtag->mData is set before using getValue(), see https://github.com/Muqsit/PocketMine-MP/blob/b7100070e2b2071a1b38579d337362e579dfbef9/src/pocketmine/tile/FlowerPot.php#L35-#L40

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible for a plugin to unset them though. Unlikely: yes, but still possible

Copy link
Contributor Author

@Muqsit Muqsit Aug 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jasonwynn10 Even before this commit was done, it was possible to unset this value. But if you meant unsetting and then defining another tag type for the value then I think the plugin should be blamed for their incorrect usages.

@@ -74,7 +74,7 @@ public function close(){
}

public function saveNBT(){
$this->namedtag->Items = new ListTag("Items", []);
$this->namedtag->Items->setValue([]);
$this->namedtag->Items->setTagType(NBT::TAG_Compound);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dktapps
Copy link
Member

dktapps commented Jul 30, 2017

Looks good at first glance, I'll review this properly later when I have the brainpower to do so.

@dktapps dktapps added Category: Core Related to internal functionality Category: API Related to the plugin API PR: Contribution labels Jul 30, 2017
@@ -170,7 +169,7 @@ public function setItem(int $index, Item $item){
}
$this->namedtag->Items[$i] = $d;
}else{
$this->namedtag->Items[$i] = $d;
$this->namedtag->Items[$i]= $d;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatting

@dktapps
Copy link
Member

dktapps commented Jul 31, 2017

Since there is a lot of undefined behaviour around the NBT implementation (type checking and such) it is sometimes preferable to create a new NBT tag to ensure that the tag is of the expected type (plugins can cause problems, as seen in earlier comments).

Your alterations to the spawn compound handling are reasonable. A possible improvement might be to make getSpawnCompound() final and have a separate abstract method something like addAdditionalSpawnData() which would be called by getSpawnCompound(). That would prevent accidents with forgetting the parent call and would also ensure that future additions must follow the new rules - this PR, for example, does not clean up the Bed tile implementation I added since this PR was opened. If I hadn't remembered beds myself it would have gone unnoticed.

@Muqsit
Copy link
Contributor Author

Muqsit commented Jul 31, 2017

Nice, this also reduces some boilerplate code.

@dktapps
Copy link
Member

dktapps commented Aug 2, 2017

Looks good to me, have you tested this fully?

@Muqsit
Copy link
Contributor Author

Muqsit commented Aug 2, 2017

@dktapps Yes, I've re-tested it after the bed tile commit.

@@ -89,29 +86,24 @@ public function getLine(int $index) : string{
if($index < 0 or $index > 3){
throw new \InvalidArgumentException("Index must be in the range 0-3!");
}
return (string) $this->namedtag["Text" . ($index + 1)];
return $this->namedtag{"Text" . ($index + 1)}->getValue();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed something?

Copy link
Contributor Author

@Muqsit Muqsit Aug 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The casting was unneeded because we're using getValue()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not talking about the cast. You're missing a ->.

The cast wouldn't be needed regardless (it's there to shut PhpStorm up because it can't determine the type of the value gotten from the tag).

@dktapps dktapps force-pushed the master branch 2 times, most recently from bc6a8c7 to fdf7184 Compare August 4, 2017 12:20
@dktapps dktapps merged commit 7d3fca8 into pmmp:master Aug 6, 2017
@Muqsit
Copy link
Contributor Author

Muqsit commented Aug 6, 2017

:D

@dktapps dktapps added Type: Enhancement Contributes features or other improvements to PocketMine-MP and removed Type: Contribution labels Nov 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: API Related to the plugin API Category: Core Related to internal functionality Type: Enhancement Contributes features or other improvements to PocketMine-MP
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants