Hi guys, I'm currently testing out some mob equipment. As far as I have it running now I am working with MobArmorEquipmentPacket which is sent to all players when the entity wears armor: PHP: $pk = new MobArmorEquipmentPacket(); $pk->eid = $this->entity->getId(); $pk->slots = [ $this->boots !== null ? $this->boots->getId() : ItemIds::AIR, $this->leggings !== null ? $this->leggings->getId() : ItemIds::AIR, $this->chestplate !== null ? $this->chestplate->getId() : ItemIds::AIR, $this->helmet !== null ? $this->helmet->getId() : ItemIds::AIR ]; $pk->encode(); $pk->isEncoded = true; $this->sendPacketToPlayers($pk); This works just fine when Entity is spawned. I can see that the Entity wears some armor stuff. But when logging out and logging in back again - of course - the entity doesn't wear any items anymore. So my thoughts were: when a player logs in - send a packet for each entity which has equipped something to the player. Is that correct? I don't think so. My specific question: do we need to set data properties on the entity additionally - or is NBT data sufficient? The NBT data then looks like this: PHP: // feet, legs, chest, head - store armor content to NBT $armor[0] = new CompoundTag("0", [ "Count" => new IntTag("Count", 1), "Damage" => new IntTag("Damage", 10), "id" => new IntTag("id", $this->boots !== null ? $this->boots->getId() : ItemIds::AIR), ]); $armor[1] = new CompoundTag("1", [ "Count" => new IntTag("Count", 1), "Damage" => new IntTag("Damage", 10), "id" => new IntTag("id", $this->leggings !== null ? $this->leggings->getId() : ItemIds::AIR), ]); $armor[2] = new CompoundTag("2", [ "Count" => new IntTag("Count", 1), "Damage" => new IntTag("Damage", 10), "id" => new IntTag("id", $this->chestplate !== null ? $this->chestplate->getId() : ItemIds::AIR), ]); $armor[3] = new CompoundTag("3", [ "Count" => new IntTag("Count", 1), "Damage" => new IntTag("Damage", 10), "id" => new IntTag("id", $this->helmet !== null ? $this->helmet->getId() : ItemIds::AIR), ]); $this->entity->namedtag->ArmorItems = new ListTag(self::NBT_KEY_ARMOR_ITEMS, $armor); This are just examples! I assume that the client doesn't really bother about NBT - as far as i saw - NBT is only used for storing / reading data from NBT store. So I assume that I need to set data properties or data flags on the entity. But at the moment I have no clue which to set. Any help would be really appreciated.
This is a perfect example of the confusion created by using NBT for in memory stuff, Blame :shoghicp: NBT is, like you said, only to be used for storage. So actually what you want to do is store the armoritems on the entity (with NBT) and read them out on each player join and then send the MobArmorEquipmentPacket using the data you read. PM apparently doesn't do that yet, proper entity support is ToDo.
I've to say that sending the MobArmorEquipmentPacket/MobEquipmentPacket doesn't work with PlayerJoinEvent. It seems, that the Entity is not completely spawned (when the server is restarted e.g.) or there's something not really initialized with the Player - so the Packet seems to be not recognized by the client - the entities just hold nothing. What i made now: every time a player joins - all entities that have equipment set a flag which is used in onUpdate of the entity. When the flag is set - the entity "broadcasts" its equipment again to all players. This is not nice and a workaround - but for now i don't see another way to do it. Just wanted to report back - in case any other developer stumbles across this.
It's always a hassle with delayed tasks. Sometimes it takes longer to initialize, sometimes shorter. I've enough experience to tell you, that when it comes to async tasks - you have to keep a lot of things in mind. And additionally, there can be graphical glitches (you see an entity wearing nothing, a second later - it wears something) - of course it's also possible with the onUpdate method. But the onUpdate workaround is more specific and more "safe" I would say. But anyway - your proposal may also be a way to go - thanks for your help
I'm not talking about async tasks. Just run a delayed task a few ticks after the join event so that the player can load in the surrounding chunks before trying to send them the entities with their data.
I'll give it a try this weekend EDIT: works. Need some more testing. But in general the delayed approach works. Thanks again for your thoughts!