I'm working on a BlockHunt "AI", It spawns falling sand entitys as packets with a command (for now), how can I change the "entity's" position to follow the player? CODE: PHP: const NETWORK_ID = 66;public function spawnTo($player){ foreach($this->getServer()->getOnlinePlayers() as $p){ $pk = new AddEntityPacket(); $pk->eid = Entity::$entityCount++; $pk->type = self::NETWORK_ID; $pk->x = $player->x + .2; $pk->y = $player->y + 1; $pk->z = $player->z; $pk->yaw = $player->yaw; $pk->pitch = $player->pitch; $pk->metadata = [ 15 => [0, 1], 20 => [2, rand(1,20)] ]; $p->dataPacket($pk); } }
It like the pet plugin from LBCore the pet follow you so if you can change it up you can let the block follow you.
It's quite easy. Change the entity id of the sand to the player. Then despawnToAll the player. After that, if you want the player back then respawn to all... BTW, if you don't understand please don't use the leaked lbcore's example. Thanks.
Be honest, did you tried the search bar? This is what I found: http://forums.pocketmine.net/threads/help-with-datapacket.16692/#post-159776
Spawning entity with same eId will synchronize movement, except.. block will be spawned on player eye height.
The answer for this thread is in the code I show there. Juggling bug fix: PHP: // Add this to onUpdate() function to avoid entity jumping/** @var Player $this->owner */$this->level->addEntityMovement($this->owner->x >> 4, $this->owner->z >> 4, $this->getId(), $this->owner->x, $this->owner->y + 0.49000001, $this->z, $this->owner->yaw, $this->owner->pitch, $this->owner->yaw); Disguise code: PHP: // Use this code to change player entity to FallingSand or custom like my Block entity class// Which basically extends FallingSand/*** Will turn player into block!* Hiding block should be done with function Block::hide();** @param Player $player player to change* @param Integer $id Block id* @param Integer $damage and Block meta data*/public function disguise(Player $player, $id, $damage){# Hideforeach($this->getServer()->getOnlinePlayers() as $for){if($player !== $for) $for->hidePlayer($player);}# Add Block entity$entity = Entity::createEntity("Block", $player->getLevel()->getChunk($player->x >> 4, $player->z >> 4), new CompoundTag("", ["Pos" => new ListTag("Pos", [new DoubleTag("", $player->x),new DoubleTag("", $player->y),new DoubleTag("", $player->z)]),"Motion" => new ListTag("Motion", [new DoubleTag("", 0),new DoubleTag("", 0),new DoubleTag("", 0)]),"Rotation" => new ListTag("Rotation", [new FloatTag("", 0),new FloatTag("", 0)]),"TileID" => new IntTag("TileID", $id),"Data" => new ByteTag("Data", $damage),"Owner" => new LongTag("Owner", $player),]));foreach($this->getServer()->getOnlinePlayers() as $for){$entity->spawnTo($for);}return true;} This is class I made for my BlockHunt Spoiler: BlockHunt PHP: <?phpnamespace sbh\Entity;use sc\Utils\SupremeTextFormat as Text;use pocketmine\entity\Living;use pocketmine\entity\Entity;use pocketmine\entity\FallingSand;use pocketmine\block\Block as BlockBlock;use pocketmine\event\entity\EntityBlockChangeEvent;use pocketmine\event\entity\EntityDamageEvent;use pocketmine\item\Item as ItemItem;use pocketmine\math\Vector3;use pocketmine\nbt\tag\ByteTag;use pocketmine\nbt\tag\IntTag;use pocketmine\nbt\tag\LongTag;use pocketmine\network\Network;use pocketmine\network\protocol\AddEntityPacket;use pocketmine\network\protocol\RemoveEntityPacket;use pocketmine\network\protocol\SetEntityMotionPacket;use pocketmine\Player;class Block extends Living { const NETWORK_ID = 66; const DATA_BLOCK_INFO = 20; public $width = 0.98; public $length = 0.98; public $height = 0.98; protected $blockId = 0; protected $damage; protected $solid = false; protected $solidBlocks = []; protected $solidBlock = null; protected $hide = false; protected $replaced = 0; // What block did this entity cover when turning into solid block ? protected $petrifaction = 1; protected $maxPetrifaction = 100; private $hided = false; public $canCollide = false; private $owner; public function setOwner(Player $player){ $this->owner = $player; $this->id = $player->getId(); } public function setSolid($value){ $this->solid = (bool) $value; } public function onUpdate($currentTick){ $this->level->addEntityMovement($this->owner->x >> 4, $this->owner->z >> 4, $this->getId(), $this->owner->x, $this->owner->y + 0.49000001, $this->z, $this->owner->yaw, $this->owner->pitch, $this->owner->yaw); if(!$this->owner instanceof Player or !$this->owner->isAlive() or !$this->owner->isConnected()){ unset($this->owner->entityBlock); foreach($this->solidBlocks as $k => $pos) { if($this->level->getBlock($pos) === $this->solidBlock){ $this->level->setBlock($pos, BlockBlock::get(0)); unset($this->solidBlocks[$k]); $this->solidBlock = null; } } $this->close(); return; } if($this->x != $this->lastX or $this->y != $this->lastY or $this->z != $this->lastZ){ $this->resetPetrifaction(); } $this->lastX = $this->x; $this->lastY = $this->y; $this->lastZ = $this->z; if($this->solid){ if(!$this->isOnEdge()){ $pos = new Vector3($this->getFloorX(), $this->getFloorY() + 0.6, $this->getFloorZ()); if($this->isPlaceTaken($pos) === false) { $this->hide = true; $block = BlockBlock::get($this->getBlock(), $this->getDamage()); $this->replaced = $this->level->getBlock($pos); $this->level->setBlock($pos, BlockBlock::get($this->getBlock(), $this->getDamage())); $this->solidBlocks[] = $pos; $this->solidBlock = $this->level->getBlock($pos); $this->level->setBlock($pos, $block); if ($this->hided === false) $this->getOwner()->sendMessage("> You are now solid"); } else { $this->owner->sendTip(Text::GRAY."You can't hide here"); $this->solid = false; --$this->petrifaction; } } else { $this->owner->sendTip(Text::GRAY."You are standing on edge"); } } else { $this->hide = false; } if($this->hide){ if(!$this->hided){ $pk = new RemoveEntityPacket(); $pk->eid = $this->getId(); $this->server->broadcastPacket($this->server->getOnlinePlayers(), $pk); $this->hided = true; } } else { if($this->hided){ $this->spawnToAll(); foreach($this->solidBlocks as $k => $pos) { if($this->level->getBlock($pos) === $this->solidBlock){ $this->level->setBlock($pos, $this->replaced); unset($this->solidBlocks[$k]); $this->solidBlock = null; } } $this->hided = false; } } if($this->solid){ if($this->petrifaction < $this->maxPetrifaction){ $this->solid = false; } } else { if($this->petrifaction >= $this->maxPetrifaction){ $this->solid = true; } else { $this->getOwner()->setXpProgress($this->petrifaction / $this->maxPetrifaction); $this->petrifaction++; } } $this->setPosition($this->getOwner()->getPosition()); return true; } protected function initEntity(){ parent::initEntity(); if(isset($this->namedtag->TileID)){ $this->blockId = $this->namedtag["TileID"]; }elseif(isset($this->namedtag->Tile)){ $this->blockId = $this->namedtag["Tile"]; $this->namedtag["TileID"] = new IntTag("TileID", $this->blockId); } if(isset($this->namedtag->Data)){ $this->damage = $this->namedtag["Data"]; } if(isset($this->namedtag->Owner)){ $this->setOwner($this->namedtag["Owner"]); if($this->owner instanceof Player === false){ $this->close(); } } else { $this->close(); return; } if(isset ($this->owner->entityBlock)){ // Remove old Owner's entity block $this->owner->entityBlock->close(); } else { $this->owner->entityBlock = $this; } if($this->blockId === 0){ $this->close(); return; } $this->lastX = $this->x; $this->lastY = $this->y; $this->lastZ = $this->z; $this->setDataProperty(self::DATA_BLOCK_INFO, self::DATA_TYPE_INT, $this->getBlock() | ($this->getDamage() << 8)); $this->spawnToALl(); } public function isPlaceTaken(Vector3 $pos){ $b = $this->level->getBlockIdAt($pos->x, $pos->y, $pos->z); $ignore = [0, 8, 9, 78, 59]; // Air, Water, Snow etc. should be ignored :) return in_array($b, $ignore, true) === false; } public function canCollideWith(Entity $entity){ return false; } public function changeBlock($id, $damage){ $this->resetPetrifaction(); $this->blockId = $id; $this->damage = $damage; $pk = new RemoveEntityPacket(); $pk->eid = $this->getId(); $this->server->broadcastPacket($this->server->getOnlinePlayers(), $pk); $this->spawnToAll(); } public function attack($damage, EntityDamageEvent $source){ if($source->getCause() === EntityDamageEvent::CAUSE_VOID){ parent::attack($damage, $source); } } public function getBlock(){ return $this->blockId; } public function getOwner() : Player { return $this->owner; } public function getDamage(){ return $this->damage; } public function saveNBT(){ $this->namedtag->TileID = new IntTag("TileID", $this->blockId); $this->namedtag->Data = new ByteTag("Data", $this->damage); $this->namedtag->Owner = new LongTag("Owner", $this->owner); } public function spawnTo(Player $player){ $pk = new AddEntityPacket(); $pk->type = FallingSand::NETWORK_ID; $pk->eid = $this->getId(); $pk->x = $this->x; $pk->y = $this->y - 1.62; $pk->z = $this->z; $pk->speedX = $this->motionX; $pk->speedY = $this->motionY; $pk->speedZ = $this->motionZ; $pk->yaw = $this->yaw; $pk->pitch = $this->pitch; $pk->metadata = [FallingSand::DATA_BLOCK_INFO => [Entity::DATA_TYPE_INT, $this->getBlock() | $this->getDamage() << 8]]; $player->dataPacket($pk); parent::spawnTo($player); } public function spawnToAll(){ foreach($this->getViewers() as $e){ $this->spawnTo($e); } } public function getName(){ return BlockBlock::get($this->getBlock(), $this->getDamage(), 1)->getName()." Entity"; } public function resetPetrifaction(){ $this->petrifaction = 1; // It can not be zero or it will cause errors } public function isOnEdge(){ $flX = $this->x; $flZ = $this->z; $newX = $flX + 0.20; $newZ = $flZ + 0.20; if(intval($flX) < intval($newX) or intval($flX) > intval($newX) or intval($flZ) < intval($newZ) or intval($flZ) > intval($newZ)) return true; return false; } public function __destruct(){ if($this->owner->isConnected()){ foreach($this->server->getOnlinePlayers() as $player){ $player->showPlayer($player); } } $this->close(); }} All I want to say: Use the same eId and PocketMine will handle movement, except.. the entity juggling bug must be fixed by yourself. Similar thread: http://forums.pocketmine.net/threads/disquising-players-entity.12531/#post-125969
You can look into @Falk MobDisguise code, and use similar packet hacks to properly animate falling sand. Just remember to add a "No AI" tag to the disguise, so sand can properly move with the player without falling inside ground