From 67f0dac3beb2fdac7e5f43f2389f95fee4f80996 Mon Sep 17 00:00:00 2001 From: paulevsGitch Date: Thu, 8 Oct 2020 19:13:40 +0300 Subject: [PATCH] Underwater plants --- .../blocks/basis/BlockUnderwaterPlant.java | 139 ++++++++++++++++++ .../mixin/common/BoneMealItemMixin.java | 107 ++++++++++++++ .../ru/betterend/registry/BlockRegistry.java | 3 + .../betterend/blockstates/bubble_coral.json | 8 + .../betterend/models/block/bubble_coral.json | 6 + .../models/block/bubble_coral_2.json | 6 + .../betterend/models/item/bubble_coral.json | 6 + .../betterend/textures/block/bubble_coral.png | Bin 0 -> 19570 bytes 8 files changed, 275 insertions(+) create mode 100644 src/main/java/ru/betterend/blocks/basis/BlockUnderwaterPlant.java create mode 100644 src/main/java/ru/betterend/mixin/common/BoneMealItemMixin.java create mode 100644 src/main/resources/assets/betterend/blockstates/bubble_coral.json create mode 100644 src/main/resources/assets/betterend/models/block/bubble_coral.json create mode 100644 src/main/resources/assets/betterend/models/block/bubble_coral_2.json create mode 100644 src/main/resources/assets/betterend/models/item/bubble_coral.json create mode 100644 src/main/resources/assets/betterend/textures/block/bubble_coral.png diff --git a/src/main/java/ru/betterend/blocks/basis/BlockUnderwaterPlant.java b/src/main/java/ru/betterend/blocks/basis/BlockUnderwaterPlant.java new file mode 100644 index 00000000..ff1c1721 --- /dev/null +++ b/src/main/java/ru/betterend/blocks/basis/BlockUnderwaterPlant.java @@ -0,0 +1,139 @@ +package ru.betterend.blocks.basis; + +import java.util.List; +import java.util.Random; + +import com.google.common.collect.Lists; + +import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; +import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.Fertilizable; +import net.minecraft.block.FluidFillable; +import net.minecraft.block.Material; +import net.minecraft.block.ShapeContext; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.Enchantments; +import net.minecraft.entity.ItemEntity; +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.FluidState; +import net.minecraft.fluid.Fluids; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.context.LootContext; +import net.minecraft.loot.context.LootContextParameters; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.sound.BlockSoundGroup; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; +import net.minecraft.world.WorldAccess; +import net.minecraft.world.WorldView; +import ru.betterend.client.ERenderLayer; +import ru.betterend.client.IRenderTypeable; +import ru.betterend.registry.BlockRegistry; +import ru.betterend.registry.BlockTagRegistry; + +public class BlockUnderwaterPlant extends BlockBaseNotFull implements IRenderTypeable, Fertilizable, FluidFillable { + private static final VoxelShape SHAPE = Block.createCuboidShape(4, 0, 4, 12, 14, 12); + + public BlockUnderwaterPlant() { + super(FabricBlockSettings.of(Material.UNDERWATER_PLANT) + .breakByTool(FabricToolTags.SHEARS) + .sounds(BlockSoundGroup.WET_GRASS) + .breakByHand(true) + .noCollision()); + } + + public BlockUnderwaterPlant(int light) { + super(FabricBlockSettings.of(Material.UNDERWATER_PLANT) + .breakByTool(FabricToolTags.SHEARS) + .sounds(BlockSoundGroup.WET_GRASS) + .lightLevel(light) + .breakByHand(true) + .noCollision()); + } + + @Override + public VoxelShape getOutlineShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ePos) { + Vec3d vec3d = state.getModelOffset(view, pos); + return SHAPE.offset(vec3d.x, vec3d.y, vec3d.z); + } + + @Override + public AbstractBlock.OffsetType getOffsetType() { + return AbstractBlock.OffsetType.XZ; + } + + @Override + public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) { + BlockState down = world.getBlockState(pos.down()); + return isTerrain(down); + } + + protected boolean isTerrain(BlockState state) { + return state.isIn(BlockTagRegistry.END_GROUND) || state.getBlock() == BlockRegistry.ENDSTONE_DUST; + } + + @Override + public BlockState getStateForNeighborUpdate(BlockState state, Direction facing, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { + if (!canPlaceAt(state, world, pos)) { + return Blocks.AIR.getDefaultState(); + } + else { + return state; + } + } + + @Override + public List getDroppedStacks(BlockState state, LootContext.Builder builder) { + ItemStack tool = builder.get(LootContextParameters.TOOL); + if (tool != null && tool.getItem().isIn(FabricToolTags.SHEARS) || EnchantmentHelper.getLevel(Enchantments.SILK_TOUCH, tool) > 0) { + return Lists.newArrayList(new ItemStack(this)); + } + else { + return Lists.newArrayList(); + } + } + + @Override + public ERenderLayer getRenderLayer() { + return ERenderLayer.CUTOUT; + } + + @Override + public boolean isFertilizable(BlockView world, BlockPos pos, BlockState state, boolean isClient) { + return true; + } + + @Override + public boolean canGrow(World world, Random random, BlockPos pos, BlockState state) { + return true; + } + + @Override + public void grow(ServerWorld world, Random random, BlockPos pos, BlockState state) { + ItemEntity item = new ItemEntity(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, new ItemStack(this)); + world.spawnEntity(item); + } + + @Override + public boolean canFillWithFluid(BlockView world, BlockPos pos, BlockState state, Fluid fluid) { + return false; + } + + @Override + public boolean tryFillWithFluid(WorldAccess world, BlockPos pos, BlockState state, FluidState fluidState) { + return false; + } + + @Override + public FluidState getFluidState(BlockState state) { + return Fluids.WATER.getStill(false); + } +} diff --git a/src/main/java/ru/betterend/mixin/common/BoneMealItemMixin.java b/src/main/java/ru/betterend/mixin/common/BoneMealItemMixin.java new file mode 100644 index 00000000..caa3cac0 --- /dev/null +++ b/src/main/java/ru/betterend/mixin/common/BoneMealItemMixin.java @@ -0,0 +1,107 @@ +package ru.betterend.mixin.common; + +import java.util.Random; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.item.BoneMealItem; +import net.minecraft.item.ItemUsageContext; +import net.minecraft.util.ActionResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockPos.Mutable; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; +import ru.betterend.registry.BlockRegistry; +import ru.betterend.registry.BlockTagRegistry; +import ru.betterend.util.BlocksHelper; + +@Mixin(BoneMealItem.class) +public class BoneMealItemMixin { + private static final Direction[] DIR = BlocksHelper.makeHorizontal(); + private static final Mutable POS = new Mutable(); + + @Inject(method = "useOnBlock", at = @At("HEAD"), cancellable = true) + private void onUse(ItemUsageContext context, CallbackInfoReturnable info) { + World world = context.getWorld(); + BlockPos blockPos = context.getBlockPos(); + if (!world.isClient) { + if (world.getBlockState(blockPos).isIn(BlockTagRegistry.END_GROUND)) { + boolean consume = false; + if (world.getBlockState(blockPos).getBlock() == Blocks.END_STONE) { + BlockState nylium = getNylium(world, blockPos); + if (nylium != null) { + BlocksHelper.setWithoutUpdate(world, blockPos, nylium); + consume = true; + } + } else { + consume = growGrass(world, blockPos); + } + if (consume) { + if (!context.getPlayer().isCreative()) + context.getStack().decrement(1); + world.syncWorldEvent(2005, blockPos, 0); + info.setReturnValue(ActionResult.SUCCESS); + info.cancel(); + } + } + } + } + + private boolean growGrass(World world, BlockPos pos) { + int y1 = pos.getY() + 3; + int y2 = pos.getY() - 3; + boolean result = false; + for (int i = 0; i < 64; i++) { + int x = (int) (pos.getX() + world.random.nextGaussian() * 2); + int z = (int) (pos.getZ() + world.random.nextGaussian() * 2); + POS.setX(x); + POS.setZ(z); + for (int y = y1; y >= y2; y--) { + POS.setY(y); + BlockPos down = POS.down(); + if (world.isAir(POS) && !world.isAir(down)) { + BlockState grass = getGrassState(world, down); + if (grass != null) { + BlocksHelper.setWithoutUpdate(world, POS, grass); + result = true; + } + break; + } + } + } + return result; + } + + private BlockState getGrassState(World world, BlockPos pos) { + BlockState state = world.getBlockState(pos); + Block block = state.getBlock(); + if (block == BlockRegistry.END_MOSS || block == BlockRegistry.END_MYCELIUM) + return world.random.nextBoolean() ? BlockRegistry.CREEPING_MOSS.getDefaultState() : BlockRegistry.UMBRELLA_MOSS.getDefaultState(); + return null; + } + + private void shuffle(Random random) { + for (int i = 0; i < 4; i++) { + int j = random.nextInt(4); + Direction d = DIR[i]; + DIR[i] = DIR[j]; + DIR[j] = d; + } + } + + private BlockState getNylium(World world, BlockPos pos) { + shuffle(world.random); + for (Direction dir : DIR) { + BlockState state = world.getBlockState(pos.offset(dir)); + if (BlocksHelper.isEndNylium(state)) + return state; + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/ru/betterend/registry/BlockRegistry.java b/src/main/java/ru/betterend/registry/BlockRegistry.java index 9c1b1273..f250e441 100644 --- a/src/main/java/ru/betterend/registry/BlockRegistry.java +++ b/src/main/java/ru/betterend/registry/BlockRegistry.java @@ -26,6 +26,7 @@ import ru.betterend.blocks.EndStoneSmelter; import ru.betterend.blocks.EnderBlock; import ru.betterend.blocks.TerminiteBlock; import ru.betterend.blocks.basis.BlockGlowingFur; +import ru.betterend.blocks.basis.BlockUnderwaterPlant; import ru.betterend.blocks.basis.BlockVine; import ru.betterend.blocks.complex.WoodenMaterial; import ru.betterend.tab.CreativeTab; @@ -58,6 +59,8 @@ public class BlockRegistry { public static final Block BLUE_VINE_LANTERN = registerBlock("blue_vine_lantern", new BlockBlueVineLantern()); public static final Block BLUE_VINE_FUR = registerBlock("blue_vine_fur", new BlockGlowingFur(BLUE_VINE_SEED, 3)); + public static final Block BUBBLE_CORAL = registerBlock("bubble_coral", new BlockUnderwaterPlant(12)); + // Vines // public static final Block DENSE_VINE = registerBlock("dense_vine", new BlockVine(15, true)); diff --git a/src/main/resources/assets/betterend/blockstates/bubble_coral.json b/src/main/resources/assets/betterend/blockstates/bubble_coral.json new file mode 100644 index 00000000..55b158b5 --- /dev/null +++ b/src/main/resources/assets/betterend/blockstates/bubble_coral.json @@ -0,0 +1,8 @@ +{ + "variants": { + "": [ + { "model": "betterend:block/bubble_coral" }, + { "model": "betterend:block/bubble_coral_2" } + ] + } +} diff --git a/src/main/resources/assets/betterend/models/block/bubble_coral.json b/src/main/resources/assets/betterend/models/block/bubble_coral.json new file mode 100644 index 00000000..36a1f954 --- /dev/null +++ b/src/main/resources/assets/betterend/models/block/bubble_coral.json @@ -0,0 +1,6 @@ +{ + "parent": "betterend:block/crop_block", + "textures": { + "texture": "betterend:block/bubble_coral" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/betterend/models/block/bubble_coral_2.json b/src/main/resources/assets/betterend/models/block/bubble_coral_2.json new file mode 100644 index 00000000..1e4483f1 --- /dev/null +++ b/src/main/resources/assets/betterend/models/block/bubble_coral_2.json @@ -0,0 +1,6 @@ +{ + "parent": "betterend:block/crop_block_inverted", + "textures": { + "texture": "betterend:block/bubble_coral" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/betterend/models/item/bubble_coral.json b/src/main/resources/assets/betterend/models/item/bubble_coral.json new file mode 100644 index 00000000..2c283b30 --- /dev/null +++ b/src/main/resources/assets/betterend/models/item/bubble_coral.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "betterend:block/bubble_coral" + } +} diff --git a/src/main/resources/assets/betterend/textures/block/bubble_coral.png b/src/main/resources/assets/betterend/textures/block/bubble_coral.png new file mode 100644 index 0000000000000000000000000000000000000000..02175a2aa5704706adc6a077a5e111aad3c2a551 GIT binary patch literal 19570 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 SEh|w_+dyVjG|Q7!5&sV%tp6wg literal 0 HcmV?d00001