From c266f86b1b86adbfb8068e3c1741d8bd5c1c13d8 Mon Sep 17 00:00:00 2001 From: Dylan T Date: Sun, 10 Mar 2019 12:05:21 +0000 Subject: [PATCH] ItemEntity: introduce controls for despawn timers (#2769) This opts _not_ to expose item "age" a la #2753 because "age" is a misleading term for it. In addition, further inspection of the problem led me to realize that exposing control of that AND despawn timeout was more complicated than simply having a despawn delay timer exactly like the pickup delay one. Everyone knows a countdown timer stops at 0, so this way we don't need any method to control the limit. Closes #2667 Closes #2753 --- src/pocketmine/entity/object/ItemEntity.php | 51 ++++++++++++++++++--- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/src/pocketmine/entity/object/ItemEntity.php b/src/pocketmine/entity/object/ItemEntity.php index 9dfc73768..415b6a196 100644 --- a/src/pocketmine/entity/object/ItemEntity.php +++ b/src/pocketmine/entity/object/ItemEntity.php @@ -33,10 +33,15 @@ use pocketmine\network\mcpe\protocol\AddItemEntityPacket; use pocketmine\network\mcpe\protocol\TakeItemEntityPacket; use pocketmine\Player; use function get_class; +use function max; class ItemEntity extends Entity{ public const NETWORK_ID = self::ITEM; + public const DEFAULT_DESPAWN_DELAY = 6000; //5 minutes + public const NEVER_DESPAWN = -1; + public const MAX_DESPAWN_DELAY = 32767 + self::DEFAULT_DESPAWN_DELAY; //max value storable by mojang NBT :( + /** @var string */ protected $owner = ""; /** @var string */ @@ -56,14 +61,20 @@ class ItemEntity extends Entity{ public $canCollide = false; /** @var int */ - protected $age = 0; + protected $despawnDelay = self::DEFAULT_DESPAWN_DELAY; protected function initEntity(CompoundTag $nbt) : void{ parent::initEntity($nbt); $this->setMaxHealth(5); $this->setHealth($nbt->getShort("Health", (int) $this->getHealth())); - $this->age = $nbt->getShort("Age", $this->age); + + $age = $nbt->getShort("Age", 0); + if($age === -32768){ + $this->despawnDelay = self::NEVER_DESPAWN; + }else{ + $this->despawnDelay = max(0, self::DEFAULT_DESPAWN_DELAY - $age); + } $this->pickupDelay = $nbt->getShort("PickupDelay", $this->pickupDelay); $this->owner = $nbt->getString("Owner", $this->owner); $this->thrower = $nbt->getString("Thrower", $this->thrower); @@ -90,18 +101,18 @@ class ItemEntity extends Entity{ $hasUpdate = parent::entityBaseTick($tickDiff); - if(!$this->isFlaggedForDespawn() and $this->pickupDelay > -1 and $this->pickupDelay < 32767){ //Infinite delay + if(!$this->isFlaggedForDespawn() and $this->pickupDelay !== self::NEVER_DESPAWN){ //Infinite delay $this->pickupDelay -= $tickDiff; if($this->pickupDelay < 0){ $this->pickupDelay = 0; } - $this->age += $tickDiff; - if($this->age > 6000){ + $this->despawnDelay -= $tickDiff; + if($this->despawnDelay <= 0){ $ev = new ItemDespawnEvent($this); $ev->call(); if($ev->isCancelled()){ - $this->age = 0; + $this->despawnDelay = self::DEFAULT_DESPAWN_DELAY; }else{ $this->flagForDespawn(); $hasUpdate = true; @@ -125,7 +136,12 @@ class ItemEntity extends Entity{ $nbt = parent::saveNBT(); $nbt->setTag($this->item->nbtSerialize(-1, "Item")); $nbt->setShort("Health", (int) $this->getHealth()); - $nbt->setShort("Age", $this->age); + if($this->despawnDelay === self::NEVER_DESPAWN){ + $age = -32768; + }else{ + $age = self::DEFAULT_DESPAWN_DELAY - $this->despawnDelay; + } + $nbt->setShort("Age", $age); $nbt->setShort("PickupDelay", $this->pickupDelay); if($this->owner !== null){ $nbt->setString("Owner", $this->owner); @@ -166,6 +182,27 @@ class ItemEntity extends Entity{ $this->pickupDelay = $delay; } + /** + * Returns the number of ticks left before this item will despawn. If -1, the item will never despawn. + * + * @return int + */ + public function getDespawnDelay() : int{ + return $this->despawnDelay; + } + + /** + * @param int $despawnDelay + * + * @throws \InvalidArgumentException + */ + public function setDespawnDelay(int $despawnDelay) : void{ + if(($despawnDelay < 0 or $despawnDelay > self::MAX_DESPAWN_DELAY) and $despawnDelay !== self::NEVER_DESPAWN){ + throw new \InvalidArgumentException("Despawn ticker must be in range 0 ... " . self::MAX_DESPAWN_DELAY . " or " . self::NEVER_DESPAWN . ", got $despawnDelay"); + } + $this->despawnDelay = $despawnDelay; + } + /** * @return string */