diff --git a/src/entity/Entity.php b/src/entity/Entity.php index a431e3ecc..d492b77e0 100644 --- a/src/entity/Entity.php +++ b/src/entity/Entity.php @@ -304,12 +304,8 @@ abstract class Entity{ if($value <= 0){ throw new \InvalidArgumentException("Scale must be greater than 0"); } - $this->size = $this->getInitialSizeInfo()->scale($value); - $this->scale = $value; - - $this->recalculateBoundingBox(); - $this->networkPropertiesDirty = true; + $this->setSize($this->getInitialSizeInfo()->scale($value)); } public function getBoundingBox() : AxisAlignedBB{ @@ -329,6 +325,16 @@ abstract class Entity{ ); } + public function getSize() : EntitySizeInfo{ + return $this->size; + } + + protected function setSize(EntitySizeInfo $size) : void{ + $this->size = $size; + $this->recalculateBoundingBox(); + $this->networkPropertiesDirty = true; + } + public function isImmobile() : bool{ return $this->immobile; } diff --git a/src/entity/Living.php b/src/entity/Living.php index 401bd051d..a5b6101c9 100644 --- a/src/entity/Living.php +++ b/src/entity/Living.php @@ -116,6 +116,10 @@ abstract class Living extends Entity{ protected $sprinting = false; /** @var bool */ protected $sneaking = false; + /** @var bool */ + protected $gliding = false; + /** @var bool */ + protected $swimming = false; abstract public function getName() : string; @@ -227,6 +231,37 @@ abstract class Living extends Entity{ } } + public function isGliding() : bool{ + return $this->gliding; + } + + public function setGliding(bool $value = true) : void{ + $this->gliding = $value; + $this->networkPropertiesDirty = true; + $this->recalculateSize(); + } + + public function isSwimming() : bool{ + return $this->swimming; + } + + public function setSwimming(bool $value = true) : void{ + $this->swimming = $value; + $this->networkPropertiesDirty = true; + $this->recalculateSize(); + } + + private function recalculateSize() : void{ + $size = $this->getInitialSizeInfo(); + if($this->isSwimming() || $this->isGliding()){ + $width = $size->getWidth(); + //we don't actually know an appropriate eye height for a swimming mob, but 2/3 should be good enough. + $this->setSize((new EntitySizeInfo($width, $width, $width * 2 / 3))->scale($this->getScale())); + }else{ + $this->setSize($size->scale($this->getScale())); + } + } + public function getMovementSpeed() : float{ return $this->moveSpeedAttr->getValue(); } @@ -800,6 +835,8 @@ abstract class Living extends Entity{ $properties->setGenericFlag(EntityMetadataFlags::BREATHING, $this->breathing); $properties->setGenericFlag(EntityMetadataFlags::SNEAKING, $this->sneaking); $properties->setGenericFlag(EntityMetadataFlags::SPRINTING, $this->sprinting); + $properties->setGenericFlag(EntityMetadataFlags::GLIDING, $this->gliding); + $properties->setGenericFlag(EntityMetadataFlags::SWIMMING, $this->swimming); } protected function onDispose() : void{ diff --git a/src/event/player/PlayerToggleGlideEvent.php b/src/event/player/PlayerToggleGlideEvent.php new file mode 100644 index 000000000..c8baabd9f --- /dev/null +++ b/src/event/player/PlayerToggleGlideEvent.php @@ -0,0 +1,40 @@ +player = $player; + } + + public function isGliding() : bool{ + return $this->isGliding; + } +} diff --git a/src/event/player/PlayerToggleSwimEvent.php b/src/event/player/PlayerToggleSwimEvent.php new file mode 100644 index 000000000..382b3c687 --- /dev/null +++ b/src/event/player/PlayerToggleSwimEvent.php @@ -0,0 +1,40 @@ +player = $player; + } + + public function isSwimming() : bool{ + return $this->isSwimming; + } +} diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 52fc9e2e3..f63487ebf 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -590,16 +590,28 @@ class InGamePacketHandler extends PacketHandler{ } return true; case PlayerAction::START_GLIDE: + if(!$this->player->toggleGlide(true)){ + $this->player->sendData([$this->player]); + } + return true; case PlayerAction::STOP_GLIDE: - break; //TODO + if(!$this->player->toggleGlide(false)){ + $this->player->sendData([$this->player]); + } + return true; case PlayerAction::CRACK_BREAK: $this->player->continueBreakBlock($pos, $face); break; case PlayerAction::START_SWIMMING: - break; //TODO + if(!$this->player->toggleSwim(true)){ + $this->player->sendData([$this->player]); + } + return true; case PlayerAction::STOP_SWIMMING: - //TODO: handle this when it doesn't spam every damn tick (yet another spam bug!!) - break; + if(!$this->player->toggleSwim(false)){ + $this->player->sendData([$this->player]); + } + return true; case PlayerAction::INTERACT_BLOCK: //TODO: ignored (for now) break; case PlayerAction::CREATIVE_PLAYER_DESTROY_BLOCK: diff --git a/src/player/Player.php b/src/player/Player.php index bdbec0bb3..400a254c2 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -68,8 +68,10 @@ use pocketmine\event\player\PlayerMoveEvent; use pocketmine\event\player\PlayerQuitEvent; use pocketmine\event\player\PlayerRespawnEvent; use pocketmine\event\player\PlayerToggleFlightEvent; +use pocketmine\event\player\PlayerToggleGlideEvent; use pocketmine\event\player\PlayerToggleSneakEvent; use pocketmine\event\player\PlayerToggleSprintEvent; +use pocketmine\event\player\PlayerToggleSwimEvent; use pocketmine\event\player\PlayerTransferEvent; use pocketmine\form\Form; use pocketmine\form\FormValidationException; @@ -1768,6 +1770,26 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ return true; } + public function toggleGlide(bool $glide) : bool{ + $ev = new PlayerToggleGlideEvent($this, $glide); + $ev->call(); + if($ev->isCancelled()){ + return false; + } + $this->setGliding($glide); + return true; + } + + public function toggleSwim(bool $swimming) : bool{ + $ev = new PlayerToggleSwimEvent($this, $swimming); + $ev->call(); + if($ev->isCancelled()){ + return false; + } + $this->setSwimming($swimming); + return true; + } + public function emote(string $emoteId) : void{ $currentTick = $this->server->getTick(); if($currentTick - $this->lastEmoteTick > 5){