1. The forums will be archived and moved to a read only mode in about 2 weeks (mid march).

Tutorial Adapting old code using CompoundTags since API 3.0.0-ALPHA12

Discussion in 'Resources' started by dktapps, Jun 14, 2018.

  1. dktapps

    dktapps Administrator Staff Member PMMP Team

    Messages:
    774
    GitHub:
    dktapps
    I've seen a lot of threads on here about various issues with CompoundTags in recent months. In this thread I'm going to give a rough overview of what changed, why it changed and how to adapt your code to it.

    Something I've been working on for a long time now (several months, closing on a year) is cleaning up NBT. NBT's implementation within PocketMine-MP was absolutely terrible and a horror for maintainability.

    Following a months-long purge of the core and updating it to the new CompoundTag API added in `pocketmine/nbt` version 0.0.1 and the new ListTag API added in version 0.1.0, the API to manipulate these tags' children using dynamic fields have been removed.

    Okay, so to clear up some misunderstanding: These error messages DO NOT mean that NBT has been removed. It just means that the old method of manipulating these is no longer supported, and that you have to use the new API instead.

    A dynamic field in this case, refers to a field accessed on an object that only exists at runtime, and cannot be seen in the code. For example:
    PHP:
    class SomeClass{
        public 
    $someField//This is NOT a dynamic field because it's declared in the code
    }

    $object = new SomeClass();
    $object->aDynamicField 1//This IS a dynamic field because there is no `$aDynamicField` declared in SomeClass.

    Old code doesn't take much fixing in most cases. In all of the below examples, `$nbt` is a \pocketmine\nbt\tag\CompoundTag instance.
    A few examples:

    Removing a child tag from a compound
    PHP:
    unset($nbt->SomeTag);
    should be replaced with
    PHP:
    $nbt->removeTag("SomeTag");
    Checking if a child tag exists in a compound
    PHP:
    if(isset($nbt->SomeTag) and $nbt->SomeTag instanceof StringTag){
        
    //do whatever
    }
    should be replaced with
    PHP:
    if($nbt->hasTag("SomeTag"StringTag::class)){ //the ::class parameter is optional but recommended
        //do whatever
    }
    Getting a child tag from a compound
    PHP:
    $v $nbt["SomeTag"];
    $v $nbt->SomeTag->getValue();
    can be replaced with:
    PHP:
    $v $nbt->getTagValue("SomeTag");
    However, this is NOT RECOMMENDED, instead it's suggested that you use these functions for the sake of type safety and readability.

    Setting a child tag to a compound
    PHP:
    $nbt->SomeTag = new StringTag("SomeTag""SomeValue");
    can be replaced with
    PHP:
    $nbt->setTag(new StringTag("SomeTag""SomeValue"));
    This applies for any tag type, not just StringTag.
    However, there are a range of new convenience methods provided, like setString(), setInt(), etc, and it's recommended you migrate your code to using those.

    The old API for NBT was shockingly bad, prone to hidden bugs, easy to break and very difficult to maintain. Removing this mess has been on the agenda for a very long time.

    Additionally, we are aiming to remove all runtime NBT storage where possible. You should treat NBT as a storage format, NOT for storing values in-memory when the server is alive.

    If you have questions about this thread, please post them below.
     
    Last edited: Jun 14, 2018
    Fadhel, Flupko, Palente and 9 others like this.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.