Don’t Land on Solid Blocks

I noticed a problem when testing some refactors and new features last week. Buckeye Butterflies would die if they landed on Melons. Obviously this wasn’t intended – the extra landing blocks are meant to be where Butterflies thrive, not where they die.

The Problem


One of the refactors I was working on last week was to enable any block to become a landing block for a Butterfly or Moth. While the refactor worked, I noticed that there was a problem with Butterflies landing on solid blocks: they would suffocate and die. Since leaf blocks don’t suffocate entities, this wasn’t an easily noticed problem.

After further testing, I found that the problem was worse than I thought. When Butterflies laid eggs on these blocks, the eggs would suffocate and die.

This is a huge bug.

The Solution


I tried many things to stop this from happening. I looked at the movement code. No problems there.

I tried ensuring their position wasn’t too close. The butterflies had to be so far away from the block that it looked like they were just floating in mid-air.

Butterflies can now land on solid blocks without dying.

I tried changing bounding boxes based on their orientation. It turns out that the code to detect suffocation ignores this and creates it’s own bounding box.

Eventually, after tracking down the source of the damage I found one function that gave me the solution.

    public boolean isInWall() {
        return !this.isSleeping() && super.isInWall();
    }

This is why villagers don’t suffocate when they sleep. Technically they are inside the bed block so would die if it wasn’t for this code.

All I needed to do was to apply the same solution to Butterflies when they are landed:

    /**
     * Ignore wall collisions if the Butterfly has landed.
     * @return Always returns false.
     */
    public boolean isInWall() {
        return !this.getIsLanded() && super.isInWall();
    }

But this didn’t quite work. When Butterflies started flying again, they would still be inside the block and would suffocate a little. They didn’t die as quickly, but they still died.

Eventually, I just went with the nuclear solution:

    /**
     * Ignore wall collisions entirely.
     * @return Always returns false.
     */
    @Override
    public boolean isInWall() {
        return false;
    }

Now they just ignored suffocation damage. I applied the same solution to eggs, caterpillars, and chrysalises, since they are always on a block of some kind.

Side Effects


There have been a couple of good side effects thanks to this fix. First, since Butterflies now ignore block suffocation, they can be positioned much closer to the blocks they have landed on. This makes them look like they are actually on the block, instead of floating slightly above them. This is a great visual improvement that should increase player’s immersion.

Butterflies no longer float above blocks.

Second, even though my attempt at changing bounding boxes didn’t work, I still kept that change. Oriented bounded boxes make a lot more sense, and they improve both culling and collision detection. Now players will be less disappointed when they attempt to catch a butterfly and miss because of a misaligned bounding box.

Butterflies have bounding boxes oriented based on their landing position.

This all goes to show that fixing bugs when you find them can often improve the experience in other ways. It’s a big reason why bug fixing should always be the number one priority when considering what to work on next.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.