From 50c3748ef91bfe57080c29465600591051292381 Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 17 Jun 2023 22:47:22 +0200 Subject: [PATCH] [Change] Updated Bonemeal API for under water bonemeal --- .../bclib/api/v3/bonemeal/BlockSpreader.java | 2 +- .../bclib/api/v3/bonemeal/BonemealAPI.java | 11 +- .../v3/bonemeal/BonemealBlockSpreader.java | 2 +- .../bonemeal/TaggedBonemealBlockSpreader.java | 8 + .../api/v3/bonemeal/WaterGrassSpreader.java | 81 ++++++++++ .../bclib/mixin/common/BoneMealItemMixin.java | 144 +----------------- 6 files changed, 103 insertions(+), 145 deletions(-) create mode 100644 src/main/java/org/betterx/bclib/api/v3/bonemeal/WaterGrassSpreader.java diff --git a/src/main/java/org/betterx/bclib/api/v3/bonemeal/BlockSpreader.java b/src/main/java/org/betterx/bclib/api/v3/bonemeal/BlockSpreader.java index 11609628..ed03243c 100644 --- a/src/main/java/org/betterx/bclib/api/v3/bonemeal/BlockSpreader.java +++ b/src/main/java/org/betterx/bclib/api/v3/bonemeal/BlockSpreader.java @@ -21,7 +21,7 @@ abstract class BlockSpreader implements BonemealBlockSpreader { BlockState blockState, boolean bl ) { - if (!blockGetter.getBlockState(blockPos.above()).propagatesSkylightDown(blockGetter, blockPos)) { + if (!canSpreadAt(blockGetter, blockPos)) { return false; } else { for (BlockPos testPos : BlockPos.betweenClosed( diff --git a/src/main/java/org/betterx/bclib/api/v3/bonemeal/BonemealAPI.java b/src/main/java/org/betterx/bclib/api/v3/bonemeal/BonemealAPI.java index 56ecd078..5c868c45 100644 --- a/src/main/java/org/betterx/bclib/api/v3/bonemeal/BonemealAPI.java +++ b/src/main/java/org/betterx/bclib/api/v3/bonemeal/BonemealAPI.java @@ -7,6 +7,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.TagKey; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; @@ -91,9 +92,13 @@ public class BonemealAPI { * @return A valid spreader instance, or {@code null} */ @ApiStatus.Internal - public BonemealBlockSpreader blockSpreaderForState(@NotNull BlockState state) { + public BonemealBlockSpreader blockSpreaderForState( + BlockGetter blockGetter, + BlockPos pos, + @NotNull BlockState state + ) { for (var e : taggedSpreaders.entrySet()) { - if (state.is(e.getKey())) { + if (state.is(e.getKey()) && e.getValue().canSpreadAt(blockGetter, pos)) { return e.getValue(); } } @@ -111,7 +116,7 @@ public class BonemealAPI { BlockState blockState = level.getBlockState(blockPos); BonemealBlockSpreader spreader = org.betterx.bclib.api.v3.bonemeal.BonemealAPI .INSTANCE - .blockSpreaderForState(blockState); + .blockSpreaderForState(level, blockPos, blockState); if (spreader != null) { if (spreader.isValidBonemealSpreadTarget(level, blockPos, blockState, level.isClientSide)) { diff --git a/src/main/java/org/betterx/bclib/api/v3/bonemeal/BonemealBlockSpreader.java b/src/main/java/org/betterx/bclib/api/v3/bonemeal/BonemealBlockSpreader.java index 49249cf0..9343879a 100644 --- a/src/main/java/org/betterx/bclib/api/v3/bonemeal/BonemealBlockSpreader.java +++ b/src/main/java/org/betterx/bclib/api/v3/bonemeal/BonemealBlockSpreader.java @@ -8,7 +8,7 @@ import net.minecraft.world.level.block.state.BlockState; public interface BonemealBlockSpreader { boolean isValidBonemealSpreadTarget(BlockGetter blockGetter, BlockPos blockPos, BlockState blockState, boolean bl); - + boolean canSpreadAt(BlockGetter blockGetter, BlockPos blockPos); boolean performBonemealSpread( ServerLevel serverLevel, diff --git a/src/main/java/org/betterx/bclib/api/v3/bonemeal/TaggedBonemealBlockSpreader.java b/src/main/java/org/betterx/bclib/api/v3/bonemeal/TaggedBonemealBlockSpreader.java index 6b0e5b29..11419ba9 100644 --- a/src/main/java/org/betterx/bclib/api/v3/bonemeal/TaggedBonemealBlockSpreader.java +++ b/src/main/java/org/betterx/bclib/api/v3/bonemeal/TaggedBonemealBlockSpreader.java @@ -1,6 +1,8 @@ package org.betterx.bclib.api.v3.bonemeal; +import net.minecraft.core.BlockPos; import net.minecraft.tags.TagKey; +import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; @@ -11,6 +13,12 @@ class TaggedBonemealBlockSpreader extends BlockSpreader { this.blockTag = blockTag; } + @Override + public boolean canSpreadAt(BlockGetter blockGetter, BlockPos blockPos) { + final BlockState aboveState = blockGetter.getBlockState(blockPos.above()); + return aboveState.isAir() && aboveState.propagatesSkylightDown(blockGetter, blockPos); + } + @Override protected boolean isValidSource(BlockState state) { return state.is(blockTag); diff --git a/src/main/java/org/betterx/bclib/api/v3/bonemeal/WaterGrassSpreader.java b/src/main/java/org/betterx/bclib/api/v3/bonemeal/WaterGrassSpreader.java new file mode 100644 index 00000000..b80823ab --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v3/bonemeal/WaterGrassSpreader.java @@ -0,0 +1,81 @@ +package org.betterx.bclib.api.v3.bonemeal; + +import org.betterx.bclib.util.BlocksHelper; +import org.betterx.bclib.util.WeightedList; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class WaterGrassSpreader extends TaggedBonemealBlockSpreader { + public WaterGrassSpreader(TagKey sourceBlockTag) { + super(sourceBlockTag); + } + + @Override + public boolean canSpreadAt(BlockGetter blockGetter, BlockPos blockPos) { + final BlockState stateAbove = blockGetter.getBlockState(blockPos.above()); + return !stateAbove.getFluidState().isEmpty() && stateAbove.is(Blocks.WATER); + } + + @Override + public boolean isValidBonemealSpreadTarget( + BlockGetter blockGetter, + BlockPos blockPos, + BlockState blockState, + boolean bl + ) { + return canSpreadAt(blockGetter, blockPos); + } + + @Override + public boolean performBonemealSpread( + ServerLevel level, + RandomSource randomSource, + BlockPos pos, + BlockState blockState + ) { + final BlockPos.MutableBlockPos currentPos = new BlockPos.MutableBlockPos(); + final WeightedList> sourceSet = new WeightedList<>(); + BuiltInRegistries.BLOCK.getTagOrEmpty(blockTag).forEach(c -> sourceSet.add(c, 1)); + + int y1 = pos.getY() + 3; + int y2 = pos.getY() - 3; + boolean result = false; + for (byte i = 0; i < 64; i++) { + int x = (int) (pos.getX() + level.random.nextGaussian() * 2); + int z = (int) (pos.getZ() + level.random.nextGaussian() * 2); + currentPos.setX(x); + currentPos.setZ(z); + for (int y = y1; y >= y2; y--) { + currentPos.setY(y); + BlockPos down = currentPos.below(); + if (BlocksHelper.isFluid(level.getBlockState(currentPos)) + && !BlocksHelper.isFluid(level.getBlockState(down))) { + Holder grass = sourceSet.get(randomSource); + if (grass.isBound()) { + if (grass.value().canSurvive(grass.value().defaultBlockState(), level, currentPos)) { + level.setBlock(currentPos, grass.value().defaultBlockState(), BlocksHelper.SET_SILENT); + result = true; + } + } +// BiConsumer grass = getWaterGrassState(level, down); +// if (grass != null) { +// grass.accept(level, currentPos); +// result = true; +// } + + break; + } + } + } + return result; + } +} diff --git a/src/main/java/org/betterx/bclib/mixin/common/BoneMealItemMixin.java b/src/main/java/org/betterx/bclib/mixin/common/BoneMealItemMixin.java index f197bb94..c5b6a72e 100644 --- a/src/main/java/org/betterx/bclib/mixin/common/BoneMealItemMixin.java +++ b/src/main/java/org/betterx/bclib/mixin/common/BoneMealItemMixin.java @@ -1,22 +1,12 @@ package org.betterx.bclib.mixin.common; -import org.betterx.bclib.api.v2.BonemealAPI; -import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI; -import org.betterx.bclib.util.BlocksHelper; -import org.betterx.bclib.util.MHelper; - import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Vec3i; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.BoneMealItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.Property; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -24,8 +14,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.function.BiConsumer; - @Mixin(BoneMealItem.class) public class BoneMealItemMixin { @Unique @@ -36,33 +24,11 @@ public class BoneMealItemMixin { Level world = context.getLevel(); final BlockPos blockPos = context.getClickedPos(); if (!world.isClientSide()) { - if (BonemealAPI.isTerrain(world.getBlockState(blockPos).getBlock())) { - boolean consume = false; - if (BonemealAPI.isSpreadableTerrain(world.getBlockState(blockPos).getBlock())) { - BlockState terrain = bclib_getSpreadable(world, blockPos); - if (terrain != null) { - BlocksHelper.setWithoutUpdate(world, blockPos, terrain); - consume = true; - } - } else { - BlockState stateAbove = world.getBlockState(blockPos.above()); - if (!stateAbove.getFluidState().isEmpty()) { - if (stateAbove.is(Blocks.WATER)) { - consume = bclib_growWaterGrass(world, blockPos); - } - } else if (stateAbove.isAir()) { - consume = bclib_growLandGrass(world, blockPos); - } - } - if (consume) { - if (!context.getPlayer().isCreative()) { - context.getItemInHand().shrink(1); - } - world.levelEvent(2005, blockPos, 0); - info.setReturnValue(InteractionResult.SUCCESS); - info.cancel(); - } + + if (!context.getPlayer().isCreative()) { + context.getItemInHand().shrink(1); } + } } @@ -80,106 +46,4 @@ public class BoneMealItemMixin { cir.setReturnValue(true); } } - - @Unique - private boolean bclib_growLandGrass(Level level, BlockPos pos) { - int y1 = pos.getY() + 3; - int y2 = pos.getY() - 3; - boolean result = false; - for (byte i = 0; i < 64; i++) { - int x = (int) (pos.getX() + level.random.nextGaussian() * 2); - int z = (int) (pos.getZ() + level.random.nextGaussian() * 2); - BCLIB_BLOCK_POS.setX(x); - BCLIB_BLOCK_POS.setZ(z); - for (int y = y1; y >= y2; y--) { - BCLIB_BLOCK_POS.setY(y); - BlockPos down = BCLIB_BLOCK_POS.below(); - if (level.isEmptyBlock(BCLIB_BLOCK_POS) && !level.isEmptyBlock(down)) { - BiConsumer grass = bclib_getLandGrassState(level, down); - if (grass != null) { - grass.accept(level, BCLIB_BLOCK_POS); - result = true; - } - break; - } - } - } - return result; - } - - @Unique - private boolean bclib_growWaterGrass(Level level, BlockPos pos) { - int y1 = pos.getY() + 3; - int y2 = pos.getY() - 3; - boolean result = false; - for (byte i = 0; i < 64; i++) { - int x = (int) (pos.getX() + level.random.nextGaussian() * 2); - int z = (int) (pos.getZ() + level.random.nextGaussian() * 2); - BCLIB_BLOCK_POS.setX(x); - BCLIB_BLOCK_POS.setZ(z); - for (int y = y1; y >= y2; y--) { - BCLIB_BLOCK_POS.setY(y); - BlockPos down = BCLIB_BLOCK_POS.below(); - if (BlocksHelper.isFluid(level.getBlockState(BCLIB_BLOCK_POS)) && !BlocksHelper.isFluid(level.getBlockState( - down))) { - BiConsumer grass = bclib_getWaterGrassState(level, down); - if (grass != null) { - grass.accept(level, BCLIB_BLOCK_POS); - result = true; - } - break; - } - } - } - return result; - } - - @Unique - private BiConsumer bclib_getLandGrassState(Level level, BlockPos pos) { - BlockState state = level.getBlockState(pos); - return BonemealAPI.getLandGrass(BiomeAPI.getBiomeID(level.getBiome(pos)), state.getBlock(), level.getRandom()); - } - - @Unique - private BiConsumer bclib_getWaterGrassState(Level level, BlockPos pos) { - BlockState state = level.getBlockState(pos); - return BonemealAPI.getWaterGrass(BiomeAPI.getBiomeID(level.getBiome(pos)), state.getBlock(), level.getRandom()); - } - - @Unique - private BlockState bclib_getSpreadable(Level level, BlockPos pos) { - Vec3i[] offsets = MHelper.getOffsets(level.getRandom()); - BlockState center = level.getBlockState(pos); - for (Vec3i dir : offsets) { - BlockPos p = pos.offset(dir); - BlockState state = level.getBlockState(p); - Block terrain = BonemealAPI.getSpreadable(state.getBlock()); - if (center.is(terrain)) { - if (bclib_haveSameProperties(state, center)) { - for (Property property : center.getProperties()) { - state = state.setValue(property, center.getValue(property)); - } - } - return state; - } - } - return null; - } - - @Unique - private boolean bclib_haveSameProperties(BlockState state1, BlockState state2) { - Property[] properties1 = state1.getProperties().toArray(new Property[0]); - Property[] properties2 = state2.getProperties().toArray(new Property[0]); - if (properties1.length != properties2.length) { - return false; - } - for (int i = 0; i < properties1.length; i++) { - String name1 = properties1[i].getName(); - String name2 = properties2[i].getName(); - if (!name1.equals(name2)) { - return false; - } - } - return true; - } } \ No newline at end of file