Fix crash when looking at crops in certain situations

This commit is contained in:
Sollace 2023-08-10 12:44:38 +01:00
parent 15d43d5ab1
commit 8ab8ec9de3
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
3 changed files with 21 additions and 14 deletions

View file

@ -1,10 +1,12 @@
package com.minelittlepony.unicopia.block; package com.minelittlepony.unicopia.block;
import java.util.Arrays; import java.util.Arrays;
import com.minelittlepony.unicopia.util.PosHelper;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes; import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView; import net.minecraft.world.BlockView;
@ -46,18 +48,10 @@ public interface SegmentedBlock {
boolean isNext(BlockState state); boolean isNext(BlockState state);
default BlockPos getTip(BlockView world, BlockPos startingPos) { default BlockPos getTip(BlockView world, BlockPos startingPos) {
while (isNext(world.getBlockState(startingPos.up())) && !world.isOutOfHeightLimit(startingPos)) { return PosHelper.traverseChain(world, startingPos, Direction.UP, this::isNext);
startingPos = startingPos.up();
}
return startingPos;
} }
default BlockPos getRoot(BlockView world, BlockPos startingPos) { default BlockPos getRoot(BlockView world, BlockPos startingPos) {
while (isBase(world.getBlockState(startingPos.down())) && !world.isOutOfHeightLimit(startingPos)) { return PosHelper.traverseChain(world, startingPos, Direction.DOWN, this::isBase);
startingPos = startingPos.down();
}
return startingPos;
} }
} }

View file

@ -76,7 +76,7 @@ public class SegmentedCropBlock extends CropBlock implements SegmentedBlock {
int height = (tip.getY() - root.getY()); int height = (tip.getY() - root.getY());
BlockState tipState = world.getBlockState(tip); 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; double offset = (root.getY() - pos.getY()) * 16;
@ -106,16 +106,16 @@ public class SegmentedCropBlock extends CropBlock implements SegmentedBlock {
@Override @Override
public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
BlockPos tip = getTip(world, pos); 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; return;
} }
if (world.getBaseLightLevel(tip, 0) >= 9) { if (world.getBaseLightLevel(tip, 0) >= 9) {
int age = getAge(state); int age = getAge(state);
if (age < getMaxAge()) { 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) { if (random.nextInt((int)(BASE_GROWTH_CHANCE / moisture) + 1) == 0) {
world.setBlockState(pos, withAge(age + 1), Block.NOTIFY_LISTENERS); world.setBlockState(pos, withAge(age + 1), Block.NOTIFY_LISTENERS);
propagateGrowth(world, pos, state); propagateGrowth(world, pos, state);

View file

@ -11,11 +11,13 @@ import java.util.stream.StreamSupport;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.Axis; import net.minecraft.util.math.Direction.Axis;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
public interface PosHelper { public interface PosHelper {
@ -65,4 +67,15 @@ public interface PosHelper {
} }
}, false); }, false);
} }
static BlockPos traverseChain(BlockView world, BlockPos startingPos, Direction chainDirection, Predicate<BlockState> 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();
}
} }