PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/src/pocketmine/command/defaults/CaveCommand.php

https://gitlab.com/matthww/Elywing
PHP | 351 lines | 261 code | 27 blank | 63 comment | 54 complexity | bfe9627438ff2b0a2bbf89d225c35df2 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 Lesser 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://itxtech.org
  18. *
  19. */
  20. namespace pocketmine\command\defaults;
  21. use pocketmine\block\Air;
  22. use pocketmine\block\Block;
  23. use pocketmine\block\Lava;
  24. use pocketmine\block\Water;
  25. use pocketmine\command\CommandSender;
  26. use pocketmine\event\TranslationContainer;
  27. use pocketmine\item\Item;
  28. use pocketmine\level\Level;
  29. use pocketmine\level\Position;
  30. use pocketmine\math\Vector3;
  31. use pocketmine\Player;
  32. use pocketmine\utils\TextFormat;
  33. class CaveCommand extends VanillaCommand{
  34. public function __construct($name){
  35. parent::__construct(
  36. $name,
  37. "Generate a cave",
  38. "%pocketmine.commands.cave.usage"
  39. );
  40. $this->setPermission("pocketmine.command.cave");
  41. }
  42. public function execute(CommandSender $sender, $commandLabel, array $args){
  43. if(!$this->testPermission($sender)){
  44. return true;
  45. }
  46. //TODO: Get rid of this and add support for relative coordinaties
  47. if($sender instanceof Player and $args[0] == "getmypos"){
  48. $sender->sendMessage("Your position: ({$sender->getX()}, {$sender->getY()}, {$sender->getZ()}, {$sender->getLevel()->getFolderName()})");
  49. return true;
  50. }
  51. //0:旋转角度 1:洞穴长度 2:分叉数 3:洞穴强度
  52. if(count($args) != 8){
  53. $sender->sendMessage(new TranslationContainer("commands.generic.usage", [$this->usageMessage]));
  54. return false;
  55. }
  56. $level = $sender->getServer()->getLevelByName($args[7]);
  57. if(!$level instanceof Level){
  58. $sender->sendMessage(TextFormat::RED ."Wrong LevelName");
  59. return false;
  60. }
  61. $pos = new Position($args[4], $args[5], $args[6], $level);
  62. $caves[0] = isset($args[0]) ? $args[0] : mt_rand(1, 360);
  63. $caves[1] = isset($args[1]) ? $args[1] : mt_rand(10, 300);
  64. $caves[2] = isset($args[2]) ? $args[2] : mt_rand(1, 6);
  65. $caves[4] = isset($args[3]) ? $args[3] : mt_rand(1, 10);
  66. $caves[3] = [false, true, true];
  67. $sender->sendMessage(new TranslationContainer("pocketmine.commands.cave.info", [$caves[0], $caves[1], $caves[2], $caves[3]]));
  68. $sender->sendMessage(new TranslationContainer(TextFormat::YELLOW . "%pocketmine.commands.cave.start"));
  69. $sender->sendMessage($pos->x . " " . $pos->y . " " . $pos->z);
  70. $this->caves($pos, $caves);
  71. $sender->sendMessage(new TranslationContainer(TextFormat::GREEN . "%pocketmine.commands.cave.success"));
  72. return true;
  73. }
  74. public function chu($v1, $v2){
  75. if($v2 == 0) return 0;
  76. return $v1 / $v2;
  77. }
  78. public function getDirectionVector($yaw, $pitch){
  79. $y = -\sin(\deg2rad($pitch));
  80. $xz = \cos(\deg2rad($pitch));
  81. $x = -$xz * \sin(\deg2rad($yaw));
  82. $z = $xz * \cos(\deg2rad($yaw));
  83. $temporalVector = new Vector3($x, $y, $z);
  84. return $temporalVector->normalize();
  85. }
  86. public function caves(Position $pos, $cave, $tt = false){
  87. $x = $pos->x;
  88. $y = $pos->y;
  89. $z = $pos->z;
  90. $level = $pos->getLevel();
  91. $ls = $cave[1]; //长度
  92. $cv = $cave[2]; //分叉数
  93. $lofs = $ls / $cave[2];
  94. $ls2 = $lofs;
  95. $yaw = $cave[0];
  96. if($cave[0] >= 0 || $cave[0] < 0){
  97. }else{
  98. $yaw = mt_rand(0, 100) * 72;
  99. }
  100. $pitch = -45;
  101. //$pi = M_PI / 180;
  102. $s1 = [$x, $y, $z];
  103. $s2 = [$x, $y, $z];
  104. //$i = -10 + mt_rand(0, 100) * 0.2;
  105. //$i = mt_rand(8, 25) / 10;
  106. $i = 1;
  107. for($u = 0; $u <= $ls; $u += $i){
  108. if($pitch > 12) $pitch = -45;
  109. $pitch += 5 + mt_rand(0, 5);
  110. $pos->getLevel()->getServer()->getLogger()->debug("[Caves] ".TextFormat::YELLOW . "yaw: $yaw pitch: $pitch");
  111. if($tt) $pitch = mt_rand(0, 100) * 0.05;
  112. //$s2[0] = $s1[0] -\sin($yaw / 180 * M_PI) * \cos($pitch / 180 * M_PI) * $i;
  113. //$s2[1] = $s1[1] +\sin($pitch / 180 * M_PI) * $i;
  114. //$s2[2] = $s1[2] + \cos($yaw / 180 * M_PI) * \cos($pitch / 180 * M_PI) * $i;
  115. #echo "s1: ";
  116. //var_dump($s1);
  117. $see = $this->getDirectionVector($yaw, $pitch);
  118. $s2[0] = $s1[0] + $see->x * $i;
  119. $s2[1] = $s1[1] - $see->y * $i;
  120. $s2[2] = $s1[2] + $see->z * $i;
  121. //echo "s2: ";
  122. //var_dump($s2);
  123. if($s2[1] < 10){
  124. $s2[1] = 10 + mt_rand(0, 10);
  125. }
  126. if($u > $lofs){
  127. $cv--;
  128. if($cave[3][1] === false) $cv = 0;
  129. $lofs += $ls2;
  130. $newPos = new Position($s2[0], $s2[1], $s2[2], $level);
  131. $this->caves($newPos, [$yaw + 90 * (round(mt_rand(0, 100) / 100) * 2 - 1), $ls - $u, $cv, [false, $cave[3][1], $cave[3][2]], 0], $tt);
  132. }
  133. //$exPos = new Position($s2[0], $s2[1], $s2[2], $level);
  134. //$this->explodeBlocks($exPos, mt_rand(2, 4), mt_rand(1, 4));
  135. if(mt_rand(0, 100) > 80){
  136. $add = mt_rand(-10, 10);
  137. }else{
  138. $add = mt_rand(-45, 45);
  139. }
  140. $yaw = $yaw + $add;
  141. $yaw = $yaw % 360;
  142. $yaw = $yaw >= 0 ? $yaw : 360 + $yaw;
  143. //$i = 5 + mt_rand(0, 100) * 0.05;
  144. $x = $s1[0];
  145. $y = $s1[1];
  146. $z = $s1[2];
  147. $x2 = $s2[0];
  148. $y2 = $s2[1];
  149. $z2 = $s2[2];
  150. $l = max(abs($x - $x2), abs($y - $y2), abs($z - $z2));
  151. for($m = 0; $m <= $l; $m++){
  152. //$v = $level->getBlock(new Vector3(round($this->chu($x + $m, $l * ($x2 - $x))), round($y + $this->chu($m, $l * ($y2 - $y))), round($z + $this->chu($m, $l * ($z2 - $z)))))->getId();
  153. //if ($v != 0 and $v != 95)
  154. $liu = mt_rand(0, 200) == 100;
  155. $this->fdx(round($x + $this->chu($m, $l * ($x2 - $x))), round($y + $this->chu($m, $l * ($y2 - $y))), round($z + $this->chu($m, $l * ($z2 - $z))), $level, $liu);
  156. }
  157. $s1 = [$s2[0], $s2[1], $s2[2]];
  158. }
  159. if(mt_rand(0, 10) >= 5 and $s2[1] <= 40){
  160. $this->lavaSpawn($level, $s2[0], $s2[1], $s2[2]);
  161. }
  162. /*
  163. if ($cave[3][0]) {
  164. $l = $cave[4];
  165. $x = $s2[0];
  166. $y = $s2[1];
  167. $z = $s2[2];
  168. for ($i = -$l; $i <= $l; $i += 2) {
  169. for ($j = -$l; $j <= $l; $j += 2) {
  170. if ($i * $i + $j * $j <= pow($l - 0.3 * $l * mt_rand(0, 1000) / 1000, 2)) {
  171. if ($level->getBlock(new Vector3($x + $i, $y - 1, $z + $j))->getId() != 0) {
  172. $this->fdx($x + $i, $y - 1 + 2 * mt_rand(0, 1000) / 1000, $z + $j, $level);
  173. }
  174. }
  175. if ($i * $i + $j * $j <= pow($l - 0.5 * $l * mt_rand(0, 1000) / 1000, 2)) {
  176. if ($level->getBlock(new Vector3($x + $i, $y + 3, $z + $j))->getId() != 0) {
  177. $this->fdx($x + $i, $y + 3 + 2 * mt_rand(0, 1000) / 1000, $z + $j, $level);
  178. }
  179. }
  180. }
  181. }
  182. //if ($level->getBlock(new Vector3($s2[0], $s2[1] - 4, $s2[2]))->getId() != 0 && $cave[3][2] && mt_rand(0, 100) / 100 > 0.5) $this->tiankengy($level, $s2[0], $s2[1], $s2[2], $l * 0.6, 11, 0);
  183. } else if ($cave[3][2]) {
  184. $l = $cave[4];
  185. if ($pitch < -10 && $pitch > -45 && $level->getBlock(new Vector3($s2[0], $s2[1] - 3, $s2[2]))->getId() != 0) $this->tiankengy($level, $s2[0], $s2[1], $s2[2], $l / 2, 11, 0);
  186. }*/
  187. //echo "\n 矿洞生成完成\n";
  188. }
  189. public function lavaSpawn(Level $level, $x, $y, $z){
  190. $level->getServer()->getLogger()->info("生成岩浆中 " . "floor($x)" . ", " . "floor($y)" . ", " . floor($z));
  191. for($xx = $x - 20; $xx <= $x + 20; $xx++){
  192. for($zz = $z - 20; $zz <= $z + 20; $zz++){
  193. for($yy = $y; $yy > $y - 4; $yy--){
  194. $id = $level->getBlockIdAt($xx, $yy, $zz);
  195. if($id == 0){
  196. $level->setBlockIdAt($xx, $yy, $zz, 10);
  197. $level->setBlockDataAt($xx, $yy, $zz, 0);
  198. }
  199. }
  200. }
  201. }
  202. $level->setBlock(new Vector3($x, $y, $z), new Lava());
  203. }
  204. public function explodeBlocks(Position $source, $rays = 16, $size = 4){
  205. $vector = new Vector3(0, 0, 0);
  206. $vBlock = new Vector3(0, 0, 0);
  207. $stepLen = 0.3;
  208. $mRays = \intval($rays - 1);
  209. $affectedBlocks = array();
  210. for($i = 0; $i < $rays; ++$i){
  211. for($j = 0; $j < $rays; ++$j){
  212. for($k = 0; $k < $rays; ++$k){
  213. if($i === 0 or $i === $mRays or $j === 0 or $j === $mRays or $k === 0 or $k === $mRays){
  214. $vector->setComponents($i / $mRays * 2 - 1, $j / $mRays * 2 - 1, $k / $mRays * 2 - 1);
  215. $vector->setComponents(($vector->x / ($len = $vector->length())) * $stepLen, ($vector->y / $len) * $stepLen, ($vector->z / $len) * $stepLen);
  216. $pointerX = $source->x;
  217. $pointerY = $source->y;
  218. $pointerZ = $source->z;
  219. for($blastForce = $size * (\mt_rand(700, 1300) / 1000); $blastForce > 0; $blastForce -= $stepLen * 0.75){
  220. $x = (int) $pointerX;
  221. $y = (int) $pointerY;
  222. $z = (int) $pointerZ;
  223. $vBlock->x = $pointerX >= $x ? $x : $x - 1;
  224. $vBlock->y = $pointerY >= $y ? $y : $y - 1;
  225. $vBlock->z = $pointerZ >= $z ? $z : $z - 1;
  226. if($vBlock->y < 0 or $vBlock->y > 127){
  227. break;
  228. }
  229. $block = $source->getLevel()->getBlock($vBlock);
  230. if($block->getId() !== 0){
  231. $blastForce -= (mt_rand(1, 3) / 5 + 0.3) * $stepLen;
  232. if($blastForce > 0){
  233. if(!isset($affectedBlocks[$index = (\PHP_INT_SIZE === 8 ? ((($block->x) & 0xFFFFFFF) << 35) | ((($block->y) & 0x7f) << 28) | (($block->z) & 0xFFFFFFF) : ($block->x) . ":" . ($block->y) . ":" . ($block->z))])){
  234. $affectedBlocks[$index] = $block;
  235. }
  236. }
  237. }
  238. $pointerX += $vector->x;
  239. $pointerY += $vector->y;
  240. $pointerZ += $vector->z;
  241. }
  242. }
  243. }
  244. }
  245. }
  246. foreach($affectedBlocks as $block){
  247. if($block instanceof Block){
  248. $block->getLevel()->setBlock($block, new Air(), false, false);
  249. }
  250. }
  251. }
  252. public function fdx($x, $y, $z, Level $level, $liu = false){
  253. //$this->getLogger()->info(TextFormat::GREEN."fdx!");
  254. for($i = 1; $i < mt_rand(2, 4); $i++){
  255. $level->setBlockIdAt($x + $i - 2, $y - 1, $z + 1, 0);
  256. $level->setBlockIdAt($x + $i - 2, $y - 1, $z, 0);
  257. $level->setBlockIdAt($x + $i - 2, $y - 1, $z - 1, 0);
  258. $level->setBlockIdAt($x + $i - 2, $y - 1, $z - 1, 0);
  259. $level->setBlockIdAt($x + $i - 2, $y - 1, $z + 1, 0);
  260. $level->setBlockIdAt($x + $i - 2, $y + 2, $z + 1, 0);
  261. $level->setBlockIdAt($x + $i - 2, $y + 2, $z, 0);
  262. $level->setBlockIdAt($x + $i - 2, $y + 2, $z - 1, 0);
  263. }
  264. for($i = 1; $i < mt_rand(3, 6); $i++){
  265. $level->setBlockIdAt($x + $i - 3, $y + 1, $z + 2, 0);
  266. $level->setBlockIdAt($x + $i - 3, $y + 1, $z + 1, 0);
  267. $level->setBlockIdAt($x + $i - 3, $y + 1, $z, 0);
  268. $level->setBlockIdAt($x + $i - 3, $y + 1, $z - 1, 0);
  269. $level->setBlockIdAt($x + $i - 3, $y + 1, $z - 2, 0);
  270. $level->setBlockIdAt($x + $i - 3, $y, $z + 2, 0);
  271. $level->setBlockIdAt($x + $i - 3, $y, $z + 1, 0);
  272. $level->setBlockIdAt($x + $i - 3, $y, $z, 0);
  273. $level->setBlockIdAt($x + $i - 3, $y, $z - 1, 0);
  274. $level->setBlockIdAt($x + $i - 3, $y, $z - 2, 0);
  275. }
  276. if($liu){
  277. $l = (mt_rand(0, 1) == 0) ? new Water() : new Lava();
  278. $i = mt_rand(3, 6);
  279. $level->setBlock(new Vector3($x + $i - 3, $y + 1, $z + 3), $l);
  280. }
  281. }
  282. public function ranz($a){
  283. $n = [];
  284. $j = 0;
  285. for($m = 0; $m < $a; $m++){
  286. $n[] = mt_rand(0, 999) / 1000 - 1;
  287. }
  288. for($m = 0; $m < $a; $m++){
  289. foreach($n as $q){
  290. $min = min($n);
  291. if($n[$q] == $min){
  292. $n[$q] = $j;
  293. $j++;
  294. break;
  295. }
  296. }
  297. }
  298. return $n;
  299. }
  300. public function tiankengy(Level $level, $x, $y, $z, $l, $id, $bd){
  301. if($level->getBlock(new Vector3($x, $y, $z))->getId() == 0) $level->setBlock(new Vector3($x, $y, $z), Item::get($id, $bd)->getBlock());
  302. if($l >= 0){
  303. $random = mt_rand(0, 99999) / 100000;
  304. $mz = $this->ranz(4);
  305. foreach($mz as $sss){
  306. switch($mz[$sss]){
  307. case 0:
  308. if($level->getBlock(new Vector3($x, $y, $z - 1))->getId() == 0) $this->tiankengy($level, $x, $y, $z - 1, $l - $random, $id, $bd);
  309. break;
  310. case 1:
  311. if($level->getBlock(new Vector3($x, $y, $z + 1))->getId() == 0) $this->tiankengy($level, $x, $y, $z + 1, $l - $random, $id, $bd);
  312. break;
  313. case 2:
  314. if($level->getBlock(new Vector3($x + 1, $y, $z))->getId() == 0) $this->tiankengy($level, $x + 1, $y, $z, $l - $random, $id, $bd);
  315. break;
  316. case 3:
  317. if($level->getBlock(new Vector3($x - 1, $y, $z))->getId() == 0) $this->tiankengy($level, $x - 1, $y, $z, $l - $random, $id, $bd);
  318. break;
  319. }
  320. }
  321. }
  322. }
  323. }