Solved Creating custom tile, that can hold an item

Discussion in 'Development' started by kriskotooBG, May 24, 2020 at 4:57 AM.

  1. kriskotooBG

    kriskotooBG Spider Jockey

    Messages:
    45
    GitHub:
    kriskotoobg
    Hello! I'm trying to add a custom block to the game, by overriding some unadded blocks, but i need to store some data... precisely 2 bools, and an item with all its enchants durability etc. I'm having trouble understanding how exactly pocketmine handles tiles, i tried going trough tile\chest, spawnable, and tile but couldn't figure out a lot... I think i did some stuff correctly.. but I'm not sure... Any help pointing me in the right direction, is much appreciated!

    PS:
    The part I'm struggling with is understanding how exactly the spawn process goes, and how exactly data is formated and stored...
     
  2. wolfdale

    wolfdale Zombie Pigman

    Messages:
    437
    If you are adding a tile that does not exist in the game, its best not to spawn it to the player, it might cause unexpected behavior.
    As for data just read and write your data in readSaveData and writeSaveData respectively and pocketmine will handle the rest
     
    kriskotooBG likes this.
  3. kriskotooBG

    kriskotooBG Spider Jockey

    Messages:
    45
    GitHub:
    kriskotoobg
    What would be the best approach then? The block state (meta) is dependent on the 2 bools in the tile, I have that part figured out, but how would I go about making the tile exactly? Which method spawns it in? Should I just use an already existing one?
     
  4. kriskotooBG

    kriskotooBG Spider Jockey

    Messages:
    45
    GitHub:
    kriskotoobg
    Ok, after a fresh cup of coffee, and a lot of following, i figured out how the whole spawn process works... thing is: I dont know where to start looking at the "despawning" aka when the server closes... So for now: i figured out how to spawn it and give it custom NBT, but now i need to figure out what methods save the data when the server closes and how to save an item instance to the NBT
     
  5. kriskotooBG

    kriskotooBG Spider Jockey

    Messages:
    45
    GitHub:
    kriskotoobg
    Let's see if i have this right:
    So first off we register the tile by doing
    Code:
    pocketmine\tile\Tile::registerTile("className", ["mySaveID"]);
    then, we need to create the NBT using MyTile::createNBT(): (inherited method from pocketmine\tile\Tile, which takes care of putting the coordinates and id in the NBT and calls MyTile::createAdditionalNBT() where i can put my bools in the NBT using pocketmine\nbt\CompondTag::setByte())
    Code:
    $tileNBTData = MyTile::createNBT($this, $clickedFace, $item, $placer) //args from block\MyBlock::place()
    after that, we can actually create the tile by doing:
    Code:
    Tile::createTile("mySaveID", $this->getLevel(), $tileNBTData);
    which creates a new instance of MyTile, and when pocketmine\tile\Tile is constructed, it calls MyTile::readSaveData() where i can get all my data, and then puts the tile in the world and also spawns it cause pcoketmine\tile\Spawnabe's construct method calls $this->spawnToAll();

    Did i understand everything correctly? If so, where can i start looking at how tiles get saved to the world, and what methods are called then, and what methods are called when they are loaded/instantiated
     
  6. kriskotooBG

    kriskotooBG Spider Jockey

    Messages:
    45
    GitHub:
    kriskotoobg
    thing is, I would really like to actually understand how everything works not just copy and paste random crap together and hope it works :D
     
  7. wolfdale

    wolfdale Zombie Pigman

    Messages:
    437
    Yea you got everything right, thats great!

    When i meant not spawning to the player, it means to extend Tile instead of Spawnable, so that it is not sent to the player and remains only server side.

    When a chunk is saved, it calls Tile::saveNBT() here https://github.com/pmmp/PocketMine-...mine/level/format/io/region/McRegion.php#L116
    Then Tile::saveNBT calls Tile::writeSaveData()

    When a chunk is loaded
    It calls Tile::createTile() here https://github.com/pmmp/PocketMine-MP/blob/stable/src/pocketmine/level/format/Chunk.php#L720k
    Then proceeds as you described above

    For saving and loading of items you can take a look here https://github.com/pmmp/PocketMine-MP/blob/stable/src/pocketmine/tile/ContainerTrait.php
     
    Last edited: May 25, 2020 at 6:43 AM
    kriskotooBG likes this.
  8. kriskotooBG

    kriskotooBG Spider Jockey

    Messages:
    45
    GitHub:
    kriskotoobg
    Thanks a bunch!

    Let's see if i understand everything correctly, when the server is stopping, somewhere in the process, (i will dig around, cause i wanna see the whole process)
    Code:
    pocketmine\level\format\io\region\McRegion::nbtSerialize()
    is called, which iterates over all the tiles in the passed chunk, and calls pocketmine\tile\Tile::saveNBT() on them, which takes care of creating a new pocketmine\nbt\CompondTag, and saves the ID and position to it, and then calls
    MyTile::writeSaveData(), where i can save my bools to it, and then thats saved!
    so that's how saving is done!

    Now loading:
    Somewhere in the chunk loading/initializing process (again, I'll dig a bit more to figure out the exact sequence of events)
    it grabs all the tile NBTs and re-creates the tiles by calling pocketmine\tile\createTile() with the NBT, and all the stuff that i said in my previous comment is done!

    Now, my question is, what's the difference between a spawned tile, and a tile?
    (also, did i get everything correctly? :D)

    About the item storage, I'm trying to store a single tool item, nothing more. Using that seems like an overkill? I still haven't checked it out, but isn't there a simpler way of doing it?
     
    Last edited: May 26, 2020 at 12:02 AM
  9. wolfdale

    wolfdale Zombie Pigman

    Messages:
    437
    Yea that's the idea.
    Whether it is a spawned tile just means whether the tile is sent to the player. If it is not sent, then the client doesn't know its there, which is ok if it doesn't exist in the game anyway.
    If you just want to store a single item you can do something like
    Saving:
    PHP:
     $nbt->setString("Item",$item->nbtSerialize()); 
    Loading:
    PHP:
     $item Item::nbtDeserialize($nbt->getString("Item")); 
     
    kriskotooBG likes this.
  10. kriskotooBG

    kriskotooBG Spider Jockey

    Messages:
    45
    GitHub:
    kriskotoobg
    Ok I think I'll figure it out from here! Thanks a million!
     

Share This Page

  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.