PageRenderTime 37ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/src/pocketmine/block/Fire.php

https://gitlab.com/koutyan777/Genisys
PHP | 239 lines | 158 code | 38 blank | 43 comment | 35 complexity | 812f608d3191ae93b4b785aeb583b73d MD5 | raw file
  1. <?php
  2. /*
  3. *
  4. * ____ _ _ __ __ _ __ __ ____
  5. * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
  6. * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
  7. * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
  8. * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Lesser General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * @author PocketMine Team
  16. * @link http://www.pocketmine.net/
  17. *
  18. *
  19. */
  20. namespace pocketmine\block;
  21. use pocketmine\entity\Arrow;
  22. use pocketmine\entity\Effect;
  23. use pocketmine\entity\Entity;
  24. use pocketmine\event\block\BlockBurnEvent;
  25. use pocketmine\event\entity\EntityCombustByBlockEvent;
  26. use pocketmine\event\entity\EntityDamageByBlockEvent;
  27. use pocketmine\event\entity\EntityDamageEvent;
  28. use pocketmine\item\Item;
  29. use pocketmine\level\Level;
  30. use pocketmine\math\Vector3;
  31. use pocketmine\Server;
  32. class Fire extends Flowable{
  33. protected $id = self::FIRE;
  34. /** @var Vector3 */
  35. private $temporalVector = null;
  36. public function __construct($meta = 0){
  37. $this->meta = $meta;
  38. if($this->temporalVector === null){
  39. $this->temporalVector = new Vector3(0, 0, 0);
  40. }
  41. }
  42. public function hasEntityCollision(){
  43. return true;
  44. }
  45. public function getName() : string{
  46. return "Fire Block";
  47. }
  48. public function getLightLevel(){
  49. return 15;
  50. }
  51. public function isBreakable(Item $item){
  52. return false;
  53. }
  54. public function canBeReplaced(){
  55. return true;
  56. }
  57. public function onEntityCollide(Entity $entity){
  58. $ProtectL = 0;
  59. if(!$entity->hasEffect(Effect::FIRE_RESISTANCE)){
  60. $ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
  61. if($entity->attack($ev->getFinalDamage(), $ev) === true){
  62. $ev->useArmors();
  63. }
  64. $ProtectL = $ev->getFireProtectL();
  65. }
  66. $ev = new EntityCombustByBlockEvent($this, $entity, 8, $ProtectL);
  67. if($entity instanceof Arrow){
  68. $ev->setCancelled();
  69. }
  70. Server::getInstance()->getPluginManager()->callEvent($ev);
  71. if(!$ev->isCancelled()){
  72. $entity->setOnFire($ev->getDuration());
  73. }
  74. }
  75. public function getDrops(Item $item) : array {
  76. return [];
  77. }
  78. public function onUpdate($type){
  79. if($type == Level::BLOCK_UPDATE_NORMAL or $type == Level::BLOCK_UPDATE_RANDOM or $type == Level::BLOCK_UPDATE_SCHEDULED){
  80. if(!$this->getSide(Vector3::SIDE_DOWN)->isTopFacingSurfaceSolid() and !$this->canNeighborBurn()){
  81. $this->getLevel()->setBlock($this, new Air(), true);
  82. return Level::BLOCK_UPDATE_NORMAL;
  83. }elseif($type == Level::BLOCK_UPDATE_NORMAL or $type == Level::BLOCK_UPDATE_RANDOM){
  84. $this->getLevel()->scheduleUpdate($this, $this->getTickRate() + mt_rand(0, 10));
  85. }elseif($type == Level::BLOCK_UPDATE_SCHEDULED and $this->getLevel()->getServer()->fireSpread){
  86. $forever = $this->getSide(Vector3::SIDE_DOWN)->getId() == Block::NETHERRACK;
  87. //TODO: END
  88. if(!$this->getSide(Vector3::SIDE_DOWN)->isTopFacingSurfaceSolid() and !$this->canNeighborBurn()){
  89. $this->getLevel()->setBlock($this, new Air(), true);
  90. }
  91. if(!$forever and $this->getLevel()->getWeather()->isRainy() and
  92. ($this->getLevel()->canBlockSeeSky($this) or
  93. $this->getLevel()->canBlockSeeSky($this->getSide(Vector3::SIDE_EAST)) or
  94. $this->getLevel()->canBlockSeeSky($this->getSide(Vector3::SIDE_WEST)) or
  95. $this->getLevel()->canBlockSeeSky($this->getSide(Vector3::SIDE_SOUTH)) or
  96. $this->getLevel()->canBlockSeeSky($this->getSide(Vector3::SIDE_NORTH))
  97. )
  98. ){
  99. $this->getLevel()->setBlock($this, new Air(), true);
  100. }else{
  101. $meta = $this->meta;
  102. if($meta < 15){
  103. $this->meta = $meta + mt_rand(0, 3);
  104. $this->getLevel()->setBlock($this, $this, true);
  105. }
  106. $this->getLevel()->scheduleUpdate($this, $this->getTickRate() + mt_rand(0, 10));
  107. if(!$forever and !$this->canNeighborBurn()){
  108. if(!$this->getSide(Vector3::SIDE_DOWN)->isTopFacingSurfaceSolid() or $meta > 3){
  109. $this->getLevel()->setBlock($this, new Air(), true);
  110. }
  111. }elseif(!$forever && !($this->getSide(Vector3::SIDE_DOWN)->getBurnAbility() > 0) && $meta >= 15 && mt_rand(0, 4) == 0){
  112. $this->getLevel()->setBlock($this, new Air(), true);
  113. }else{
  114. $o = 0;
  115. //TODO: decrease the o if the rainfall values are high
  116. $this->tryToCatchBlockOnFire($this->getSide(Vector3::SIDE_EAST), 300 + $o, $meta);
  117. $this->tryToCatchBlockOnFire($this->getSide(Vector3::SIDE_WEST), 300 + $o, $meta);
  118. $this->tryToCatchBlockOnFire($this->getSide(Vector3::SIDE_DOWN), 250 + $o, $meta);
  119. $this->tryToCatchBlockOnFire($this->getSide(Vector3::SIDE_UP), 250 + $o, $meta);
  120. $this->tryToCatchBlockOnFire($this->getSide(Vector3::SIDE_SOUTH), 300 + $o, $meta);
  121. $this->tryToCatchBlockOnFire($this->getSide(Vector3::SIDE_NORTH), 300 + $o, $meta);
  122. for($x = ($this->x - 1); $x <= ($this->x + 1); ++$x){
  123. for($z = ($this->z - 1); $z <= ($this->z + 1); ++$z){
  124. for($y = ($this->y -1); $y <= ($this->y + 4); ++$y){
  125. $k = 100;
  126. if($y > $this->y + 1){
  127. $k += ($y - ($this->y + 1)) * 100;
  128. }
  129. $chance = $this->getChanceOfNeighborsEncouragingFire($this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $z)));
  130. if($chance > 0){
  131. $t = ($chance + 40 + $this->getLevel()->getServer()->getDifficulty() * 7);
  132. //TODO: decrease t if the rainfall values are high
  133. if($t > 0 and mt_rand(0, $k) <= $t){
  134. $damage = min(15, $meta + mt_rand(0, 5) / 4);
  135. $this->getLevel()->setBlock($this->temporalVector->setComponents($x, $y, $z), new Fire($damage), true);
  136. $this->getLevel()->scheduleUpdate($this->temporalVector, $this->getTickRate());
  137. }
  138. }
  139. }
  140. }
  141. }
  142. }
  143. }
  144. }
  145. }
  146. return 0;
  147. }
  148. public function getTickRate() : int{
  149. return 30;
  150. }
  151. /*public function onUpdate($type){
  152. if($type === Level::BLOCK_UPDATE_NORMAL){
  153. for($s = 0; $s <= 5; ++$s){
  154. $side = $this->getSide($s);
  155. if($side->getId() !== self::AIR and !($side instanceof Liquid)){
  156. return false;
  157. }
  158. }
  159. $this->getLevel()->setBlock($this, new Air(), true);
  160. return Level::BLOCK_UPDATE_NORMAL;
  161. }elseif($type === Level::BLOCK_UPDATE_RANDOM){
  162. if($this->getSide(0)->getId() !== self::NETHERRACK){
  163. $this->getLevel()->setBlock($this, new Air(), true);
  164. return Level::BLOCK_UPDATE_NORMAL;
  165. }
  166. }
  167. return false;
  168. }*/
  169. private function tryToCatchBlockOnFire(Block $block, int $bound, int $damage){
  170. $burnAbility = $block->getBurnAbility();
  171. if(mt_rand(0, $bound) < $burnAbility){
  172. if(mt_rand(0, $damage + 10) < 5){
  173. $meta = max(15, $damage + mt_rand(0, 4) / 4);
  174. $this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new BlockBurnEvent($block));
  175. if(!$ev->isCancelled()){
  176. $this->getLevel()->setBlock($block, $fire = new Fire($meta), true);
  177. $this->getLevel()->scheduleUpdate($block, $fire->getTickRate());
  178. }
  179. }else{
  180. $this->getLevel()->setBlock($this, new Air(), true);
  181. }
  182. if($block instanceof TNT){
  183. $block->prime();
  184. }
  185. }
  186. }
  187. private function getChanceOfNeighborsEncouragingFire(Block $block){
  188. if($block->getId() !== self::AIR){
  189. return 0;
  190. }else{
  191. $chance = 0;
  192. for($i = 0; $i < 5; $i++){
  193. $chance = max($chance, $block->getSide($i)->getBurnChance());
  194. }
  195. return $chance;
  196. }
  197. }
  198. }