PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/pocketmine/tile/Dropper.php

https://gitlab.com/kennethgomad01/genisys
PHP | 287 lines | 201 code | 39 blank | 47 comment | 23 complexity | 8f4b501e2355700ba03cb2a7ada98ac6 MD5 | raw file
  1. <?php
  2. /*
  3. *
  4. * _____ _____ __ _ _ _____ __ __ _____
  5. * / ___| | ____| | \ | | | | / ___/ \ \ / / / ___/
  6. * | | | |__ | \| | | | | |___ \ \/ / | |___
  7. * | | _ | __| | |\ | | | \___ \ \ / \___ \
  8. * | |_| | | |___ | | \ | | | ___| | / / ___| |
  9. * \_____/ |_____| |_| \_| |_| /_____/ /_/ /_____/
  10. *
  11. * This program is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation, either version 3 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * @author iTX Technologies
  17. * @link https://mcper.cn
  18. *
  19. */
  20. namespace pocketmine\tile;
  21. use pocketmine\block\Block;
  22. use pocketmine\inventory\DropperInventory;
  23. use pocketmine\inventory\InventoryHolder;
  24. use pocketmine\item\Item;
  25. use pocketmine\level\format\FullChunk;
  26. use pocketmine\level\particle\SmokeParticle;
  27. use pocketmine\math\Vector3;
  28. use pocketmine\nbt\NBT;
  29. use pocketmine\nbt\tag\DoubleTag;
  30. use pocketmine\nbt\tag\FloatTag;
  31. use pocketmine\nbt\tag\ShortTag;
  32. use pocketmine\entity\Item as ItemEntity;
  33. use pocketmine\nbt\tag\CompoundTag;
  34. use pocketmine\nbt\tag\ListTag;
  35. use pocketmine\nbt\tag\IntTag;
  36. use pocketmine\nbt\tag\StringTag;
  37. class Dropper extends Spawnable implements InventoryHolder, Container, Nameable{
  38. /** @var DropperInventory */
  39. protected $inventory;
  40. protected $nextUpdate = 0;
  41. public function __construct(FullChunk $chunk, CompoundTag $nbt){
  42. parent::__construct($chunk, $nbt);
  43. $this->inventory = new DropperInventory($this);
  44. if(!isset($this->namedtag->Items) or !($this->namedtag->Items instanceof ListTag)){
  45. $this->namedtag->Items = new ListTag("Items", []);
  46. $this->namedtag->Items->setTagType(NBT::TAG_Compound);
  47. }
  48. for($i = 0; $i < $this->getSize(); ++$i){
  49. $this->inventory->setItem($i, $this->getItem($i));
  50. }
  51. $this->scheduleUpdate();
  52. }
  53. public function close(){
  54. if($this->closed === false){
  55. foreach($this->getInventory()->getViewers() as $player){
  56. $player->removeWindow($this->getInventory());
  57. }
  58. foreach($this->getInventory()->getViewers() as $player){
  59. $player->removeWindow($this->getInventory());
  60. }
  61. parent::close();
  62. }
  63. }
  64. public function saveNBT(){
  65. $this->namedtag->Items = new ListTag("Items", []);
  66. $this->namedtag->Items->setTagType(NBT::TAG_Compound);
  67. for($index = 0; $index < $this->getSize(); ++$index){
  68. $this->setItem($index, $this->inventory->getItem($index));
  69. }
  70. }
  71. /**
  72. * @return int
  73. */
  74. public function getSize(){
  75. return 9;
  76. }
  77. /**
  78. * @param $index
  79. *
  80. * @return int
  81. */
  82. protected function getSlotIndex($index){
  83. foreach($this->namedtag->Items as $i => $slot){
  84. if((int) $slot["Slot"] === (int) $index){
  85. return (int) $i;
  86. }
  87. }
  88. return -1;
  89. }
  90. /**
  91. * This method should not be used by plugins, use the Inventory
  92. *
  93. * @param int $index
  94. *
  95. * @return Item
  96. */
  97. public function getItem($index){
  98. $i = $this->getSlotIndex($index);
  99. if($i < 0){
  100. return Item::get(Item::AIR, 0, 0);
  101. }else{
  102. return NBT::getItemHelper($this->namedtag->Items[$i]);
  103. }
  104. }
  105. /**
  106. * This method should not be used by plugins, use the Inventory
  107. *
  108. * @param int $index
  109. * @param Item $item
  110. *
  111. * @return bool
  112. */
  113. public function setItem($index, Item $item){
  114. $i = $this->getSlotIndex($index);
  115. $d = NBT::putItemHelper($item, $index);
  116. if($item->getId() === Item::AIR or $item->getCount() <= 0){
  117. if($i >= 0){
  118. unset($this->namedtag->Items[$i]);
  119. }
  120. }elseif($i < 0){
  121. for($i = 0; $i <= $this->getSize(); ++$i){
  122. if(!isset($this->namedtag->Items[$i])){
  123. break;
  124. }
  125. }
  126. $this->namedtag->Items[$i] = $d;
  127. }else{
  128. $this->namedtag->Items[$i] = $d;
  129. }
  130. return true;
  131. }
  132. /**
  133. * @return DropperInventory
  134. */
  135. public function getInventory(){
  136. return $this->inventory;
  137. }
  138. public function getName() : string{
  139. return isset($this->namedtag->CustomName) ? $this->namedtag->CustomName->getValue() : "Dropper";
  140. }
  141. public function hasName(){
  142. return isset($this->namedtag->CustomName);
  143. }
  144. public function setName($str){
  145. if($str === ""){
  146. unset($this->namedtag->CustomName);
  147. return;
  148. }
  149. $this->namedtag->CustomName = new StringTag("CustomName", $str);
  150. }
  151. public function getMotion(){
  152. $meta = $this->getBlock()->getDamage();
  153. switch($meta){
  154. case Vector3::SIDE_DOWN:
  155. return [0, -1, 0];
  156. case Vector3::SIDE_UP:
  157. return [0, 1, 0];
  158. case Vector3::SIDE_NORTH:
  159. return [0, 0, -1];
  160. case Vector3::SIDE_SOUTH:
  161. return [0, 0, 1];
  162. case Vector3::SIDE_WEST:
  163. return [-1, 0, 0];
  164. case Vector3::SIDE_EAST:
  165. return [1, 0, 0];
  166. default:
  167. return [0, 0, 0];
  168. }
  169. }
  170. public function activate(){
  171. $itemIndex = [];
  172. for($i = 0; $i < $this->getSize(); $i++){
  173. $item = $this->getInventory()->getItem($i);
  174. if($item->getId() != Item::AIR){
  175. $itemIndex[] = [$i, $item];
  176. }
  177. }
  178. $max = count($itemIndex) - 1;
  179. if($max < 0) $itemArr = null;
  180. elseif($max == 0) $itemArr = $itemIndex[0];
  181. else $itemArr = $itemIndex[mt_rand(0, $max)];
  182. if(is_array($itemArr)){
  183. /** @var Item $item */
  184. $item = $itemArr[1];
  185. $item->setCount($item->getCount() - 1);
  186. $this->getInventory()->setItem($itemArr[0], $item->getCount() > 0 ? $item : Item::get(Item::AIR));
  187. $motion = $this->getMotion();
  188. $needItem = Item::get($item->getId(), $item->getDamage());
  189. $block = $this->getLevel()->getBlock($this->add($motion[0], $motion[1], $motion[2]));
  190. switch($block->getId()){
  191. case Block::CHEST:
  192. case Block::TRAPPED_CHEST:
  193. case Block::DROPPER:
  194. case Block::DISPENSER:
  195. case Block::BREWING_STAND_BLOCK:
  196. case Block::FURNACE:
  197. $t = $this->getLevel()->getTile($block);
  198. /** @var Chest|Dispenser|Dropper|BrewingStand|Furnace $t */
  199. if($t instanceof Tile){
  200. if($t->getInventory()->canAddItem($needItem)){
  201. $t->getInventory()->addItem($needItem);
  202. return;
  203. }
  204. }
  205. }
  206. $itemTag = NBT::putItemHelper($needItem);
  207. $itemTag->setName("Item");
  208. $nbt = new CompoundTag("", [
  209. "Pos" => new ListTag("Pos", [
  210. new DoubleTag("", $this->x + $motion[0] * 2 + 0.5),
  211. new DoubleTag("", $this->y + ($motion[1] > 0 ? $motion[1] : 0.5)),
  212. new DoubleTag("", $this->z + $motion[2] * 2 + 0.5)
  213. ]),
  214. "Motion" => new ListTag("Motion", [
  215. new DoubleTag("", $motion[0]),
  216. new DoubleTag("", $motion[1]),
  217. new DoubleTag("", $motion[2])
  218. ]),
  219. "Rotation" => new ListTag("Rotation", [
  220. new FloatTag("", lcg_value() * 360),
  221. new FloatTag("", 0)
  222. ]),
  223. "Health" => new ShortTag("Health", 5),
  224. "Item" => $itemTag,
  225. "PickupDelay" => new ShortTag("PickupDelay", 10)
  226. ]);
  227. $f = 0.3;
  228. $itemEntity = new ItemEntity($this->chunk, $nbt, $this);
  229. $itemEntity->setMotion($itemEntity->getMotion()->multiply($f));
  230. $itemEntity->spawnToAll();
  231. for($i = 1; $i < 10; $i++){
  232. $this->getLevel()->addParticle(new SmokeParticle($this->add($motion[0] * $i * 0.3 + 0.5, $motion[1] == 0 ? 0.5 : $motion[1] * $i * 0.3, $motion[2] * $i * 0.3 + 0.5)));
  233. }
  234. }
  235. }
  236. public function getSpawnCompound(){
  237. $c = new CompoundTag("", [
  238. new StringTag("id", Tile::DROPPER),
  239. new IntTag("x", (int) $this->x),
  240. new IntTag("y", (int) $this->y),
  241. new IntTag("z", (int) $this->z)
  242. ]);
  243. if($this->hasName()){
  244. $c->CustomName = $this->namedtag->CustomName;
  245. }
  246. return $c;
  247. }
  248. }