setPermission("pocketmine.command.particle"); } public function execute(CommandSender $sender, string $commandLabel, array $args){ if(!$this->testPermission($sender)){ return true; } if(count($args) < 7){ throw new InvalidCommandSyntaxException(); } if($sender instanceof Player){ $senderPos = $sender->getPosition(); $world = $senderPos->getWorldNonNull(); $pos = new Vector3( $this->getRelativeDouble($senderPos->getX(), $sender, $args[1]), $this->getRelativeDouble($senderPos->getY(), $sender, $args[2], 0, World::Y_MAX), $this->getRelativeDouble($senderPos->getZ(), $sender, $args[3]) ); }else{ $world = $sender->getServer()->getWorldManager()->getDefaultWorld(); $pos = new Vector3((float) $args[1], (float) $args[2], (float) $args[3]); } $name = strtolower($args[0]); $xd = (float) $args[4]; $yd = (float) $args[5]; $zd = (float) $args[6]; $count = isset($args[7]) ? max(1, (int) $args[7]) : 1; $data = isset($args[8]) ? (int) $args[8] : null; $particle = $this->getParticle($name, $data); if($particle === null){ $sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.particle.notFound", [$name])); return true; } $sender->sendMessage(new TranslationContainer("commands.particle.success", [$name, $count])); $random = new Random((int) (microtime(true) * 1000) + mt_rand()); for($i = 0; $i < $count; ++$i){ $world->addParticle($pos->add( $random->nextSignedFloat() * $xd, $random->nextSignedFloat() * $yd, $random->nextSignedFloat() * $zd ), $particle); } return true; } private function getParticle(string $name, ?int $data = null) : ?Particle{ switch($name){ case "explode": return new ExplodeParticle(); case "hugeexplosion": return new HugeExplodeParticle(); case "hugeexplosionseed": return new HugeExplodeSeedParticle(); case "bubble": return new BubbleParticle(); case "splash": return new SplashParticle(); case "wake": case "water": return new WaterParticle(); case "crit": return new CriticalParticle(); case "smoke": return new SmokeParticle($data ?? 0); case "spell": return new EnchantParticle(new Color(0, 0, 0, 255)); //TODO: colour support case "instantspell": return new InstantEnchantParticle(new Color(0, 0, 0, 255)); //TODO: colour support case "dripwater": return new WaterDripParticle(); case "driplava": return new LavaDripParticle(); case "townaura": case "spore": return new SporeParticle(); case "portal": return new PortalParticle(); case "flame": return new FlameParticle(); case "lava": return new LavaParticle(); case "reddust": return new RedstoneParticle($data ?? 1); case "snowballpoof": return new ItemBreakParticle(VanillaItems::SNOWBALL()); case "slime": return new ItemBreakParticle(VanillaItems::SLIMEBALL()); case "itembreak": if($data !== null and $data !== 0){ return new ItemBreakParticle(ItemFactory::getInstance()->get($data)); } break; case "terrain": if($data !== null and $data !== 0){ return new TerrainParticle(BlockFactory::getInstance()->get($data)); } break; case "heart": return new HeartParticle($data ?? 0); case "ink": return new InkParticle($data ?? 0); case "droplet": return new RainSplashParticle(); case "enchantmenttable": return new EnchantmentTableParticle(); case "happyvillager": return new HappyVillagerParticle(); case "angryvillager": return new AngryVillagerParticle(); case "forcefield": return new BlockForceFieldParticle($data ?? 0); case "mobflame": return new EntityFlameParticle(); } if(strpos($name, "iconcrack_") === 0){ $d = explode("_", $name); if(count($d) === 3){ return new ItemBreakParticle(ItemFactory::getInstance()->get((int) $d[1], (int) $d[2])); } }elseif(strpos($name, "blockcrack_") === 0){ $d = explode("_", $name); if(count($d) === 2){ return new TerrainParticle(BlockFactory::getInstance()->get(((int) $d[1]) & 0xff, ((int) $d[1]) >> 12)); } }elseif(strpos($name, "blockdust_") === 0){ $d = explode("_", $name); if(count($d) >= 4){ return new DustParticle(new Color(((int) $d[1]) & 0xff, ((int) $d[2]) & 0xff, ((int) $d[3]) & 0xff, isset($d[4]) ? ((int) $d[4]) & 0xff : 255)); } } return null; } }