PocketMine-MP 5.35.1 git-f412a390b8f63d0311cc1d1c81046404153b8440
Loading...
Searching...
No Matches
ParticleCommand.php
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 PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\command\defaults;
25
69use function count;
70use function explode;
71use function max;
72use function microtime;
73use function mt_rand;
74use function strtolower;
75
77
78 public function __construct(string $namespace, string $name){
79 parent::__construct(
80 $namespace,
81 $name,
82 KnownTranslationFactory::pocketmine_command_particle_description(),
83 KnownTranslationFactory::pocketmine_command_particle_usage()
84 );
85 $this->setPermission(DefaultPermissionNames::COMMAND_PARTICLE);
86 }
87
88 public function execute(CommandSender $sender, string $commandLabel, array $args){
89 if(count($args) < 7){
91 }
92
93 if($sender instanceof Player){
94 $senderPos = $sender->getPosition();
95 $world = $senderPos->getWorld();
96 $pos = new Vector3(
97 $this->getRelativeDouble($senderPos->getX(), $sender, $args[1]),
98 $this->getRelativeDouble($senderPos->getY(), $sender, $args[2], World::Y_MIN, World::Y_MAX),
99 $this->getRelativeDouble($senderPos->getZ(), $sender, $args[3])
100 );
101 }else{
102 $world = $sender->getServer()->getWorldManager()->getDefaultWorld();
103 $pos = new Vector3((float) $args[1], (float) $args[2], (float) $args[3]);
104 }
105
106 $name = strtolower($args[0]);
107
108 $xd = (float) $args[4];
109 $yd = (float) $args[5];
110 $zd = (float) $args[6];
111
112 $count = isset($args[7]) ? max(1, (int) $args[7]) : 1;
113
114 $data = $args[8] ?? null;
115
116 $particle = $this->getParticle($name, $data);
117
118 if($particle === null){
119 $sender->sendMessage(KnownTranslationFactory::commands_particle_notFound($name)->prefix(TextFormat::RED));
120 return true;
121 }
122
123 $sender->sendMessage(KnownTranslationFactory::commands_particle_success($name, (string) $count));
124
125 $random = new Random((int) (microtime(true) * 1000) + mt_rand());
126
127 for($i = 0; $i < $count; ++$i){
128 $world->addParticle($pos->add(
129 $random->nextSignedFloat() * $xd,
130 $random->nextSignedFloat() * $yd,
131 $random->nextSignedFloat() * $zd
132 ), $particle);
133 }
134
135 return true;
136 }
137
138 private function getParticle(string $name, ?string $data = null) : ?Particle{
139 switch($name){
140 case "explode":
141 return new ExplodeParticle();
142 case "hugeexplosion":
143 return new HugeExplodeParticle();
144 case "hugeexplosionseed":
145 return new HugeExplodeSeedParticle();
146 case "bubble":
147 return new BubbleParticle();
148 case "splash":
149 return new SplashParticle();
150 case "wake":
151 case "water":
152 return new WaterParticle();
153 case "crit":
154 return new CriticalParticle();
155 case "smoke":
156 return new SmokeParticle((int) ($data ?? 0));
157 case "spell":
158 return new EnchantParticle(new Color(0, 0, 0, 255)); //TODO: colour support
159 case "instantspell":
160 return new InstantEnchantParticle(new Color(0, 0, 0, 255)); //TODO: colour support
161 case "dripwater":
162 return new WaterDripParticle();
163 case "driplava":
164 return new LavaDripParticle();
165 case "townaura":
166 case "spore":
167 return new SporeParticle();
168 case "portal":
169 return new PortalParticle();
170 case "flame":
171 return new FlameParticle();
172 case "lava":
173 return new LavaParticle();
174 case "reddust":
175 return new RedstoneParticle((int) ($data ?? 1));
176 case "snowballpoof":
177 return new ItemBreakParticle(VanillaItems::SNOWBALL());
178 case "slime":
179 return new ItemBreakParticle(VanillaItems::SLIMEBALL());
180 case "itembreak":
181 if($data !== null){
182 $item = StringToItemParser::getInstance()->parse($data);
183 if($item !== null && !$item->isNull()){
184 return new ItemBreakParticle($item);
185 }
186 }
187 break;
188 case "terrain":
189 if($data !== null){
190 $block = StringToItemParser::getInstance()->parse($data)?->getBlock();
191 if($block !== null && $block->getTypeId() !== BlockTypeIds::AIR){
192 return new TerrainParticle($block);
193 }
194 }
195 break;
196 case "heart":
197 return new HeartParticle((int) ($data ?? 0));
198 case "ink":
199 return new InkParticle((int) ($data ?? 0));
200 case "droplet":
201 return new RainSplashParticle();
202 case "enchantmenttable":
203 return new EnchantmentTableParticle();
204 case "happyvillager":
205 return new HappyVillagerParticle();
206 case "angryvillager":
207 return new AngryVillagerParticle();
208 case "forcefield":
209 return new BlockForceFieldParticle((int) ($data ?? 0));
210 case "mobflame":
211 return new EntityFlameParticle();
212 case "iconcrack":
213 if($data !== null && ($item = StringToItemParser::getInstance()->parse($data)) !== null && !$item->isNull()){
214 return new ItemBreakParticle($item);
215 }
216 break;
217 case "blockcrack":
218 if($data !== null && ($block = StringToItemParser::getInstance()->parse($data)?->getBlock()) !== null && $block->getTypeId() !== BlockTypeIds::AIR){
219 return new TerrainParticle($block);
220 }
221 break;
222 case "blockdust":
223 if($data !== null){
224 //to preserve the old unlimited explode behaviour, allow this to split into at most 5 parts
225 //this allows the 4th argument to be processed normally if given without forcing it to also consume
226 //any unexpected parts
227 //we probably ought to error in this case, but this will do for now
228 $d = explode("_", $data, limit: 5);
229 if(count($d) >= 3){
230 return new DustParticle(new Color(
231 ((int) $d[0]) & 0xff,
232 ((int) $d[1]) & 0xff,
233 ((int) $d[2]) & 0xff,
234 ((int) ($d[3] ?? 255)) & 0xff
235 ));
236 }
237 }
238 break;
239 case "sonicexplosion":
240 return new SonicExplosionParticle();
241 }
242
243 return null;
244 }
245}
execute(CommandSender $sender, string $commandLabel, array $args)