From f0e7713dce53da2217d4aca397a77d9c107f5f6c Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Tue, 16 Sep 2014 11:51:31 +0200 Subject: [PATCH] Added suffocation, drowning damage. Closes #1908 --- src/pocketmine/block/Liquid.php | 9 ++++++ src/pocketmine/block/StillWater.php | 7 ----- src/pocketmine/entity/Entity.php | 44 ++++++++++++++++++++++++++++- src/pocketmine/entity/Human.php | 1 + src/pocketmine/entity/Living.php | 21 ++++++++++++++ 5 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/pocketmine/block/Liquid.php b/src/pocketmine/block/Liquid.php index 5b04662ff..a00dd1681 100644 --- a/src/pocketmine/block/Liquid.php +++ b/src/pocketmine/block/Liquid.php @@ -28,4 +28,13 @@ class Liquid extends Transparent{ public $isReplaceable = true; public $isSolid = false; public $isFullBlock = true; + + public function getFluidHeightPercent(){ + $d = $this->meta; + if($d >= 8){ + $d = 0; + } + + return ($d + 1) / 9; + } } \ No newline at end of file diff --git a/src/pocketmine/block/StillWater.php b/src/pocketmine/block/StillWater.php index 47b924303..a2f24d5d6 100644 --- a/src/pocketmine/block/StillWater.php +++ b/src/pocketmine/block/StillWater.php @@ -21,17 +21,10 @@ namespace pocketmine\block; -use pocketmine\entity\Entity; - class StillWater extends Water{ public function __construct($meta = 0){ Liquid::__construct(self::STILL_WATER, $meta, "Still Water"); $this->hardness = 500; } - public function onEntityCollide(Entity $entity){ - $entity->fallDistance = 0; - $entity->extinguish(); - } - } \ No newline at end of file diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 175edcbf6..dd40cff51 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -25,6 +25,7 @@ namespace pocketmine\entity; use pocketmine\block\Block; +use pocketmine\block\Water; use pocketmine\event\entity\EntityDamageEvent; use pocketmine\event\entity\EntityDespawnEvent; use pocketmine\event\entity\EntityLevelChangeEvent; @@ -110,6 +111,9 @@ abstract class Entity extends Position implements Metadatable{ protected $age = 0; public $height; + + public $eyeHeight = null; + public $width; public $length; @@ -153,6 +157,10 @@ abstract class Entity extends Position implements Metadatable{ throw new \Exception("Invalid garbage Chunk given to Entity"); } + if($this->eyeHeight === null){ + $this->eyeHeight = $this->height; + } + $this->id = Entity::$entityCount++; $this->justCreated = true; $this->namedtag = $nbt; @@ -674,7 +682,7 @@ abstract class Entity extends Position implements Metadatable{ } public function getEyeHeight(){ - return 0; + return $this->eyeHeight; } public function moveFlying(){ //TODO @@ -726,6 +734,40 @@ abstract class Entity extends Position implements Metadatable{ return new Position($this->x, $this->y, $this->z, $this->getLevel()); } + public function isInsideOfWater(){ + $block = $this->getLevel()->getBlock($pos = (new Vector3($this->x, $y = ($this->y + $this->getEyeHeight()), $this->z))->floor()); + + if($block instanceof Water){ + $f = ($pos->y + 1) - ($block->getFluidHeightPercent() - 0.1111111); + return $y < $f; + } + + return false; + } + + public function isInsideOfSolid(){ + for($i = 0; $i < 8; ++$i){ + $x = (($i % 2) - 0.5) * $this->width * 0.8; + $y = ((($i >> 1) % 2) - 0.5) * 0.1; + $z = ((($i >> 2) % 2) - 0.5) * $this->width * 0.8; + $block = $this->getLevel()->getBlock((new Vector3($this->x + $x, $this->y + $this->getEyeHeight() + $y, $this->z + $z))->floor()); + + if($block->isSolid){ + return true; + } + } + return false; + + $block = $this->getLevel()->getBlock($pos = (new Vector3($this->x, $y = ($this->y + $this->getEyeHeight()), $this->z))->floor()); + + if($block instanceof Water){ + $f = ($pos->y + 1) - ($block->getFluidHeightPercent() - 0.1111111); + return $y < $f; + } + + return false; + } + public function collision(){ $this->isColliding = true; $this->fallDistance = 0; diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 354e3121b..bc1868394 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -45,6 +45,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ public $width = 0.6; public $length = 0.6; public $height = 1.8; + public $eyeHeight = 1.62; public function getInventory(){ return $this->inventory; diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index eaa830035..b96024ad6 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -116,6 +116,27 @@ abstract class Living extends Entity implements Damageable{ Timings::$timerEntityBaseTick->startTiming(); parent::entityBaseTick(); + if($this->dead !== true and $this->isInsideOfSolid()){ + $this->server->getPluginManager()->callEvent($ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_SUFFOCATION, 1)); + if(!$ev->isCancelled()){ + $this->attack($ev->getFinalDamage(), $ev); + } + } + + if($this->dead !== true and $this->isInsideOfWater()){ + --$this->airTicks; + if($this->airTicks <= -20){ + $this->airTicks = 0; + + $this->server->getPluginManager()->callEvent($ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_DROWNING, 2)); + if(!$ev->isCancelled()){ + $this->attack($ev->getFinalDamage(), $ev); + } + } + + $this->extinguish(); + } + if($this->attackTime > 0){ --$this->attackTime; }