# Solved Determining Block Below Player & Subsequently Count of Blocks

Discussion in 'Spigot Plugin Development' started by WAS, May 3, 2017.

1. ### WAS

What would be the lowest impact method to determine the block below a player and how many blocks there are while flying. Currently I am using the block iterator which I know in general you should try and avoid the iterator for loops.

Code (Java):
BlockIterator trace = new BlockIterator(f.getWorld(), f.toVector(),
new Vector(BlockFace.DOWN.getModX(), BlockFace.DOWN.getModY(), BlockFace.DOWN.getModZ()), 0, 256);

Block groundBlock = null;

int toGround = 0;
while (trace.hasNext()) {
Block block = trace.next();
if (!(block.getType().equals(Material.AIR))) {
groundBlock = block;
break;
}
toGround++;
}
Would it be less expensive to check blocks by location and use a simple for loop? And by locations something like

Code (Java):
for (int i = 0; i < f.getWorld().getMaxHeight(); i++) {
Block block = f.add(0, -f.getY()-i, 0).getBlock();
if (!(block.getType().equals(Material.AIR))) {
groundBlock = block;
toGround = i;
break;
}
}

#1
Last edited: May 3, 2017
2. ### Choco Moderator

I see no reason to use a BlockIterator in a situation such as this. The only true purpose I could see for a BlockIterator for this would be if you require the last Block in the iteration, and the Vector was in an undetermined direction. In any other situation, it can be rather inefficient when there is a superior alternative (see BlockIterator's source code).

I recommend instead using a while loop to determine where the next solid block is
Code (Java):
Location playerLoc = player.getLocation();

int amount = 0;
while (!playerLoc.subtract(0, 1, 0).getBlock().getType().isSolid()) {
amount++;
}
I used Material#isSolid() just so water/lava (or any future liquids) don't count as solid blocks. They will essentially be considered as air. You're welcome to instead check if the material is not equal to air, however

EDIT: You may also get creative with a for loop:
Code (Java):
Location playerLoc = player.getLocation();

int count = 0;
for (; !playerLoc.subtract(0, 1, 0).getBlock().getType().isSolid(); count++);
(Hey look! A use for conditional statements without a body!)

#2
Last edited: May 3, 2017
• Agree x 1
3. ### WAS

I came to same conclusion after doing some timing tests. I came up with this. Using the world height just in case there is instances where the nether is below. Course it'll count over by a margin in those circumstances, but better than going stray by some chance.

Code (Java):
Block lastBlock = null;
Block groundBlock = null;
int toGround = 0;

for (int i = 0; i < f.getWorld().getMaxHeight(); i++) {
if (lastBlock == null) {
lastBlock = f.subtract(0, 1, 0).getBlock();
} else {
lastBlock = lastBlock.getLocation().subtract(0, 1, 0).getBlock();
}
if (!(lastBlock.getType().equals(Material.AIR))) {
groundBlock = lastBlock;
toGround = i;
break;
}
}

4. ### dNiym

I would suggest if you're trying to optimize get the first block, get the x y z,
for(i = y ; i > 0; i--)
If(player.getWorld().getBlockTypeIdAt(x,i,z) == Material.AIR.ordinal()) {
groundBlock = player.getWorld().getBlockAt(x,y,z);
Return;
}
getBlockTypeIdAt is faster than getting the type and material.

Sent from my iPhone using Tapatalk

5. ### WAS

I'm not sure that's true in a negligible terms (citation needed), and is also deprecated.