# 1.17.x Trying to break blocks in a spiral pattern with delay between each block

Discussion in 'Spigot Plugin Development' started by denNesLP, Jul 9, 2021.

Not open for further replies.
1. ### denNesLP

Hi. First of all: I'm quite new to creating plugins and this is my first try doing something. I learned Java in University and now i'd like to get some practise.

As it's said in the title, i'm trying to create an outgoing spiral which should mine blocks within a given radius and by itself, it's already kinda working. It's just breaking all blocks in that area instantly. For that case (and for potential performance-improvement) i want to add a delay of 10 ticks (example. Value is given via
Code (Java):
config.getLong("TicksBetweenBrokenBlocks")
).

My code, so far, looks like this:
Code (Java):
@EventHandler
public void breakBlocksSpiral(BlockBreakEvent event)
{
Location blockPos = event.getBlock().getLocation();
World w = blockPos.getWorld();
Block b = w.getBlockAt(blockPos);
for (Material material : blocks)
{
if(config.getBoolean("BreakBlocks"))
{
int x = b.getX(), y = b.getY(), z = b.getZ(); //Coordinates of the broken block

for(int h = 0; h < 32; h++)
/*I copied this part from https://stackoverflow.com/a/10607084. It creates an outgoing spiral pattern with [x, y, z] being the coordinates of the by a player broken block
and [x2, h, z2] being added to that.

[X, Z] are the outer limits of the spiral, but for now they're set to 7      */

{
int X = 7, Z = 7, x2 = 0, z2 = 0, temp, dx = 0, dz = -1; //I know, it's not pretty, but i wanna make it work first
int t = Math.max(X,Z);
int maxI = t*t;

for (int i=0; i < maxI; i++)
{
if ((-X/2 <= x2) && (x2 <= X/2) && (-Z/2 <= z2) && (z2 <= Z/2))
{
int finalX = x2;
int finalH = h;
int finalZ = z2;
Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> breakBlocks(w.getBlockAt(x + finalX, y + finalH, z + finalZ)),config.getLong("TicksBetweenBrokenBlocks")); //This is the part where i'm struggling. The method works fine without the scheduler
}
if( (x2 == z2) || ((x2 < 0) && (x2 == -z2)) || ((x2 > 0) && (x2 == 1-z2)))
{
temp=dx;
dx=-dz;
dz=temp;
}
x2+=dx;
z2+=dz;
}
}
}
}
}

private void breakBlocks(Block block)
{
for (Material dBlock : blocks) //Array 'blocks' lists blocks who are supposed to be mined. It's not a parameter because i just use one class (for now)
{
if (config.getBoolean("DropItems") && block.getType().equals(dBlock)) //DropItems states, if broken blocks should drop items or not
{
block.breakNaturally();
break;
}
else if (block.getType().equals(dBlock))
{
block.setType(Material.AIR);
break;
}
}
}
private final Material[] blocks = //Example
{
Material.STONE,
Material.DIRT
};
It would be nice if someone could help me with that

3. ### Maxx_Qc

Do you want your code to be executed x ticks later or repeat each x ticks?

Code (Java):
}, config.getLong("TicksBetweenBrokenBlocks"));
Code (Java):
}, 0L/* delay in ticks before first execution*/, config.getLong("TicksBetweenBrokenBlocks"));
You can also save this in a variable in order to cancel it at some point like so:
Code (Java):

4. ### denNesLP

I want breakBlocks to be repeated for a limited number of times, with a delay of x ticks after the last execution.

And i just tried runTaskLater and runTasktimer. All blocks got destroyed at the same time, even it happend after the delay of 40 ticks

5. ### lelesape

You are not doing it right, you are just putting the for loop inside the run method, you must pass everything in the for loops to the BukkitRunnable

6. ### Maxx_Qc

Code (Java):
new BukkitRunnable()
{
int count = 0;
@Override
public void run()
{
breakBlocks(block);
count++;

if (count > /* your number of repeated times you want*/)
cancel();
}

• Like x 1
• Optimistic x 1
7. ### denNesLP

I have no idea what i'm doing. I just know that this doesn't work:
Code (Java):

for (int h = 0; h < 32; h++)
{
int X = 7, Z = 7, x2 = 0, z2 = 0, temp, dx = 0, dz = -1;
int t = Math.max(X, Z);
int maxI = t * t;

for (int i = 0; i < maxI; i++)
{
if ((-X / 2 <= x2) && (x2 <= X / 2) && (-Z / 2 <= z2) && (z2 <= Z / 2))
{
int finalX = x2;
int finalH = h;
int finalZ = z2;
new BukkitRunnable()
{
int count = 0;
@Override
public void run()
{
breakBlocks(w.getBlockAt(x + finalX, y + finalH, z + finalZ));
count++;

if(count > maxI)
{
cancel();
}
}
}
if ((x2 == z2) || ((x2 < 0) && (x2 == -z2)) || ((x2 > 0) && (x2 == 1 - z2)))
{
temp = dx;
dx = -dz;
dz = temp;
}
x2 += dx;
z2 += dz;
}
}
Where do i need to create the new BukkitRunnable within my code?

8. ### Maxx_Qc

What the hell are doing? If you wanna do it that way (inside nested for loops) you’ll have to use runTaskLater buddy…

9. ### lelesape

You don't have to use for loops, instead, make your own "loop variables", in your case "i" and "h", let me show you an example of a "nested for loop using BukkitRunnable":

Code (Java):
new BukkitRunnable(){
int i = 0;
int j = 0;
public void run() {
if(j > 8){
//Inner for loop ends
i++;
j = 0;
if(i > 8) {
//Outer for loop ends
cancel();
return;
}
}
//Code inside for loops here
j++;
}

• Useful x 1
10. ### denNesLP

Like I said, I have no idea what I'm doing, so I'm guessing most of the time and hope that it's working in the end. Reading the spigot-documentation isn't helping much either.

I tried your way and my method looks like this now:
Code (Java):
@EventHandler
public void breakBlocks(BlockBreakEvent event)
{
Location blockPos = event.getBlock().getLocation();
World w = blockPos.getWorld();
Block b = w.getBlockAt(blockPos);
for (Material dBlock : blocks)
{
if (b.getType() == dBlock)
{
int x = b.getX(), y = b.getY(), z = b.getZ(); //Coordinates of broken block
if(config.getBoolean("BreakBlocks"))
{
new BukkitRunnable()
{
int i = 0, h = 0, X = 7, Z = 7, x2 = 0, z2 = 0, temp, dx = 0, dz = -1;
public void run()
{
if (h > 32) //Heightlimit for blocks
{
i++;
h = 0;
if (i > ((Math.max(X, Z)) * (Math.max(X, Z))))
{
cancel();
}
}

//This code is supposed to break blocks in form of a spiral
if ((-X / 2 <= x2) && (x2 <= X / 2) && (-Z / 2 <= z2) && (z2 <= Z / 2))
{
breakBlock(w.getBlockAt(x + x2, y + h, z + z2));
}
if ((x2 == z2) || ((x2 < 0) && (x2 == -z2)) || ((x2 > 0) && (x2 == 1 - z2)))
{
temp = dx;
dx = -dz;
dz = temp;
}
x2 += dx;
z2 += dz;
h++;
}
}
}
}
}
It just broke 4 out of ~100 blocks, (so there's still stg wrong with the spiral-algorithm) but with the delay i wanted. Thank you

11. ### lelesape

Glad the delay works for you now, I hope you understand what and why is happening. Now is time to add debug messages and see why is it only breaking 4 out of 100 block. By the way, instead of
Code (Java):
i > ((Math.max(X,Z)) * (Math.max(X,Z)))
you could just do
Code (Java):
i > Math.pow(Math.max(X,Z), 2)

• Like x 1
• Useful x 1
12. ### denNesLP

It's working now. Just doesn't look that pretty yet...

Thanks to both of you
Code (Java):
@EventHandler
public void breakBlocks(BlockBreakEvent event)
{
Location blockPos = event.getBlock().getLocation();
World w = blockPos.getWorld();
Block b = w.getBlockAt(blockPos);
for (Material dBlock : blocks)
{
if (b.getType() == dBlock)
{
int x = b.getX(), y = b.getY(), z = b.getZ(); //Coordinates of broken block
if(config.getBoolean("BreakBlocks"))
{
new BukkitRunnable()
{
int i = 0, j = 0, h = 0, X = 7, Z = 7, x2 = 0, z2 = 0, temp, dx = 0, dz = -1;

public void run()
{
if (j > (Z + 1))
{
i++;
j = 0;
if (i > (X + 1))
{
h++;
i = 0;
dx = 0;
dz = -1;
x2 = 0;
z2 = 0;
if (h > 32)
{
cancel();
}
}
}
if ((-X / 2 <= x2) && (x2 <= X / 2) && (-Z / 2 <= z2) && (z2 <= Z / 2))
{
breakBlock(w.getBlockAt(x + x2, y + h, z + z2));
}
if ((x2 == z2) || ((x2 < 0) && (x2 == -z2)) || ((x2 > 0) && (x2 == 1 - z2)))
{
temp = dx;
dx = -dz;
dz = temp;
}
x2 += dx;
z2 += dz;
j++;
}