Hello everyone! I've lately been working on a worldedit plugin, and noticed there have been a lot of questions about how to make shapes properly, and settings those for example to a given block. This tutorial is to clear that up for you. This tutorial is also aimed to make the process as mathematically easy as possible, and efficient, due to the scanning in for example a sphere not processing the same block additional times. This tutorial is made for people who already know at least a decent amount of PocketMine API. Now, let's start shall we? Let's begin by making the most basic shape: A cube. Spoiler: Creating a cube We first start by introducing a new function. There are a couple required things to make a cube. In our case, this is a center Vector3, and a radius. PHP: public function createCube(Position $center, float $radius) { for($x = $center->x - $radius; $x <= $center->x + $radius; $x++) { for($y = $center->y - $radius; $y <= $center->y + $radius; $y++) { for($z = $center->z - $radius; $z <= $center->z + $radius; $z++) { $center->getLevel()->setBlock(new Vector3($x, $y, $z), Block::get(Block::STONE), false, false); // Set block update to false to decrease lag with big areas. } } }} Now that we know how to make a cube, it is time to move on to the sphere. A sphere is the shape most coders have problems with. Spheres can be made using a lot of math, but there is a way easier way to do it without a big amount of math knowledge. Spoiler: Creating a sphere PHP: public function createSphere(Position $center, float $radius) { $radiusSquared = $radius * $radius; for($x = $center->x - $radius; $x <= $center->x + $radius; $x++) { $xsquared = ($center->x - $x) * ($center->x - $x); for($y = $center->y - $radius; $y <= $center->y + $radius; $y++) { $ysquared = ($center->y - $y) * ($center->y - $y); for($z = $center->z - $radius; $z <= $center->z + $radius; $z++) { $zsquared = ($center->z = $z) * ($center->z - $z); if($xsquared + $ysquared + $zsquared < $radiusSquared) { $center->getLevel()->setBlock(new Vector3($x, $y, $z), Block::get(Block::STONE), false, false); } } } }} The code to make a sphere may look quite complicated at first, but if you look at it a couple times, you should slowly start to understand what it does. As soon as you understand how the sphere works, we can continue to the cylinder. Creating a cylinder is basically a combination between the creating of a cube, and the creating of a sphere. Spoiler: Creating a cylinder PHP: // A cylinder is super similar to a sphere. Just change one for loop, and you're set!public function createCylinder(Position $center, float $radius) { $radiusSquared = $radius * $radius; for($x = $center->x - $radius; $x <= $center->x + $radius; $x++) { $xsquared = ($center->x - $x) * ($center->x - $x); for($y = $center->y - $radius; $y <= $center->y + $radius; $y++) { for($z = $center->z - $radius; $z <= $center->z + $radius; $z++) { $zsquared = ($center->z = $z) * ($center->z - $z); if($xsquared + $zsquared < $radiusSquared) { $center->getLevel()->setBlock(new Vector3($x, $y, $z), Block::get(Block::STONE), false, false); } } } }} I made this in the hope that it'll be helpful, so please make sure to tell me if something is wrong or doesn't work, or if you need more help. I hope this tutorial helped some of you! This method CAN be used for particles too. To make a good looking sphere though, you would have to replace for example $x++ with $x += 0.05 for a higher density. Please note that setting blocks on this way is not very efficient when setting a huge amount of blocks. This tutorial is mainly for the part of showing how to do it, and could, when not handled with care, freeze the server.
wat. that makes me get more confusion... TOO MANY MATHS! (I don't understand a single thing of it) (Whats an SPhere?)
The math required is honestly really little. Just try to visualize what you're doing with the code. Once you get that, it's really easy to understand
Don't use a 'for' loop in the completed WE plug, setting large amounts of blocks would cause the Main thread to be "frozen" for too long.
True. I'll add a warning. What do you suggest otherwise next to setting it in a repeating task or an async? My world edit plugin doesn't allow to set big amounts of blocks anyways. It limits a radius bigger than 10.
In my WE plug (not public) I used one of the tasks shown here: http://blog.falkirks.com/setting-huge-areas-of-blocks/ the tick separated would work allowing the server to respond to players in-between block sets.
If you replace $i++ with ++$i you can save some time as pre incrementing doesn't make a copy of the var. Idk how much time you can actually save with that though, but your's is the farthest in optimization already. Except for... (I could be wrong), setBlock outside a for loop might be better. PHP: public function createCube(Vector3 $center, float $radius) { $blockdata = []; for($x = $center->x - $radius; $x <= $center->x + $radius; $x++) { for($y = $center->y - $radius; $y <= $center->y + $radius; $y++) { for($z = $center->z - $radius; $z <= $center->z + $radius; $z++) { $blockdata[] = [$x, $y, $z]; } } } foreach($blockdata as $coord) { //I think Location and Position have getLevel(), not sure about Vector3 having one. $center->getLevel()->setBlockIdAt($coord[0], $coord[1], $coord[2], Block::get(Block::STONE)); //no updates are sent. }} Nice work btw xd
isnt looping for the same thing better then merging the loop since now you just run x2 amounts of loops + array access + array storing also recommend reading up http://blog.falkirks.com/setting-huge-areas-of-blocks/ like imagical gamer said it is defenitly a good read if you want to make plugin that sets huge amount of date why doe? why not just let them do it, it is not like it will break the internal machanism if i really have to do that, that will be my last resort i will also add a limit overwrite config for users who know what they are doing
Lol this thread was never meant to be a subject of optimizing block placement. It was just to show people how to make basic shapes. Of course there's ways to optimize it, but I leave that to the others.
Also this code http://pastebin.com/Lta2E2U0 is work's too And it create sphere with radius = 30 for 1-2 sec
Add ellipsoid, elliptical cylinder, rotated cylinder, distorted cylinder, distorted sphere, parallelepiped and elliptical frustum! How long it takes primarily depends on the machine and extra actions executed. "1-2 sec" is meaningless in this situation.
I made this with $center as Position object in my head, for example a block. A basic Vector3 won't work, you'll have to make at least a new Position object for it, or get the block at that location.