Optimization: Check for air beneath leaf block.
BrekiTomasson opened this issue ยท 5 comments
Just to test a theory, I placed a bunch of slabs under the leaves of a tree, and it continued to generate leaves that didn't go anywhere. Maybe there should be some kind of check to ensure that there's actually air beneath the leaf block before generating particles? There could even be a setting for users to define whether they want a minimum of 1, 2 or 3 air blocks before particles are generated.
Image included of particles on top of stone slabs in a tree.
This comes down to the isBottomLeafBlock()
test:
which works differently to the water drips from leaves you see during rain:
BlockPos belowPos = pos.down();
BlockState blockState = world.getBlockState(belowPos);
return !blockState.isSideSolidFullSquare(world, belowPos, Direction.UP)
|| !blockState.isOpaque();
No matter how often I look at it, it trips me up how different they are; why does the drip check have a negation before isSideSolidFullSquare()
while isBottomLeafBlock()
does not?
Why was !blockState.isOpaque()
replaced by blockState.isTranslucent(world, belowPos) || blockState.isSolidBlock(world, belowPos)
?
Actually, version 1.0 didn't have blockState.isSolidBlock(world, belowPos)
, so it was "not opaque" vs "translucent", which seems to make a bit more sense.
Why can't we simply check for air?
Because then leaves wouldn't fall if there's a fence, an open trapdoor, a button or maybe flowing water or a modded fruit below - it'd be too exclusive.
On the other end we need to ensure that leaves don't fall directly between leaf blocks - although we can always test for that directly via blockState.getBlock() instanceof LeavesBlock
, so we shouldn't worry about that too much.
What do these properties mean?
In short: Absolutely no clue.
I wrote some interpretations that I had to delete because they all seemed to be wrong, so here's just some fax:
Tested on an oak leaf block (the block itself, not what's below it):
blockState.isSideSolidFullSquare(): false
blockState.isTranslucent(): false
blockState.isSolidBlock(): false
blockState.isOpaque(): false
blockState.getMaterial().isSolid(): true
The wiki describes solid blocks as ones which have collisions - that may match with getMaterial().isSolid()
.
Note the seemingly contradictory statement isTranslucent()
= isOpaque()
.
What to do
Maybe we should do an actual collision test before spawning a particle at a specific location, e.g. there's
world.getBlockCollisions(@Nullable Entity entity, Box box)
and Particle
by default has a bounding box with an 0.2 spacing, so I think
new Box(0.1, 0.0, 0.1, 0.1, -0.2, 0.1)
offset by the position should work.
We can extend that box vertically down as far as we like to check if there's anything in the way.
Since I was so close, I just implemented it:
It seems to work pretty well!
I also just noticed: Do falling leaves have common drift? They all seem to shoot out in a certain direction.
...
Yes they do!
The last 3 arguments are the velocity, which are used to give the leaf it's color - and the leaf constructor just keeps (actually reduces) the values, so all same-colored leafes will drift in the same direction.
It makes it look like there's wind, which actually works in the mods favor.
Many great comments, and I see no reason to argue against anything you're saying here. The only thing I can imagine adding to the conversation at this point is that we should keep the check that detects whether there's another leaf block beneath as well, since there are mods such as Tiny Tweaks that remove the collision box from leaves. If we'd only check for collision and not identify the "lowest" leaf blocks in a cluster of leaves, then we'd potentially end up with a lot of particles being generated.
I also think we should look into the idea of checking the distance to collision, as I'm sure we could get some performance benefit if we remove particles that only travel 1 block before collision. I'm thinking of Oak trees with leaves just one block off the ground and several modded trees where you have layers of leaves looking something like this: (X for leaves, O for logs):
XOX
O
XXOXX
O
XXXOXXX
O
XXXXXOXXXXX
O
XXXXXXXOXXXXXXX
O
O
O
If we're just checking for collision one block away, there are 22 leaf blocks that would be generating particles that fall down 1 block before hitting another leaf block, not just the 14 bottom leaf blocks that are visible from the user's perspective.