From 8ab8ec9de30378277bd3128e7e19a9b443511980 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 10 Aug 2023 12:44:38 +0100 Subject: [PATCH] Fix crash when looking at crops in certain situations --- .../unicopia/block/SegmentedBlock.java | 14 ++++---------- .../unicopia/block/SegmentedCropBlock.java | 8 ++++---- .../minelittlepony/unicopia/util/PosHelper.java | 13 +++++++++++++ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/SegmentedBlock.java b/src/main/java/com/minelittlepony/unicopia/block/SegmentedBlock.java index 441e9882..e374473e 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/SegmentedBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/SegmentedBlock.java @@ -1,10 +1,12 @@ package com.minelittlepony.unicopia.block; import java.util.Arrays; +import com.minelittlepony.unicopia.util.PosHelper; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.BlockView; @@ -46,18 +48,10 @@ public interface SegmentedBlock { boolean isNext(BlockState state); default BlockPos getTip(BlockView world, BlockPos startingPos) { - while (isNext(world.getBlockState(startingPos.up())) && !world.isOutOfHeightLimit(startingPos)) { - startingPos = startingPos.up(); - } - - return startingPos; + return PosHelper.traverseChain(world, startingPos, Direction.UP, this::isNext); } default BlockPos getRoot(BlockView world, BlockPos startingPos) { - while (isBase(world.getBlockState(startingPos.down())) && !world.isOutOfHeightLimit(startingPos)) { - startingPos = startingPos.down(); - } - - return startingPos; + return PosHelper.traverseChain(world, startingPos, Direction.DOWN, this::isBase); } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/SegmentedCropBlock.java b/src/main/java/com/minelittlepony/unicopia/block/SegmentedCropBlock.java index 97e0225e..36c6b924 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/SegmentedCropBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/SegmentedCropBlock.java @@ -76,7 +76,7 @@ public class SegmentedCropBlock extends CropBlock implements SegmentedBlock { int height = (tip.getY() - root.getY()); BlockState tipState = world.getBlockState(tip); - double tipHeight = SegmentedBlock.getHeight(((SegmentedCropBlock)tipState.getBlock()).getAge(tipState)); + double tipHeight = tipState.getBlock() instanceof SegmentedCropBlock tipBlock ? SegmentedBlock.getHeight(tipBlock.getAge(tipState)) : 0; double offset = (root.getY() - pos.getY()) * 16; @@ -106,16 +106,16 @@ public class SegmentedCropBlock extends CropBlock implements SegmentedBlock { @Override public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { BlockPos tip = getTip(world, pos); - BlockPos base = getRoot(world, pos); + BlockPos root = getRoot(world, pos); - if (base.getY() != pos.getY()) { + if (root.getY() != pos.getY()) { return; } if (world.getBaseLightLevel(tip, 0) >= 9) { int age = getAge(state); if (age < getMaxAge()) { - float moisture = CropBlock.getAvailableMoisture(world.getBlockState(base).getBlock(), world, base); + float moisture = CropBlock.getAvailableMoisture(world.getBlockState(root).getBlock(), world, root); if (random.nextInt((int)(BASE_GROWTH_CHANCE / moisture) + 1) == 0) { world.setBlockState(pos, withAge(age + 1), Block.NOTIFY_LISTENERS); propagateGrowth(world, pos, state); diff --git a/src/main/java/com/minelittlepony/unicopia/util/PosHelper.java b/src/main/java/com/minelittlepony/unicopia/util/PosHelper.java index 587e1bbb..603a2c2c 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/PosHelper.java +++ b/src/main/java/com/minelittlepony/unicopia/util/PosHelper.java @@ -11,11 +11,13 @@ import java.util.stream.StreamSupport; import com.google.common.collect.Lists; +import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction.Axis; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; +import net.minecraft.world.BlockView; import net.minecraft.world.World; public interface PosHelper { @@ -65,4 +67,15 @@ public interface PosHelper { } }, false); } + + static BlockPos traverseChain(BlockView world, BlockPos startingPos, Direction chainDirection, Predicate isInChain) { + BlockPos.Mutable mutablePos = new BlockPos.Mutable(); + mutablePos.set(startingPos); + do { + mutablePos.move(chainDirection); + } while (isInChain.test(world.getBlockState(mutablePos)) && !world.isOutOfHeightLimit(mutablePos)); + + mutablePos.move(chainDirection.getOpposite()); + return mutablePos.toImmutable(); + } }