From e931be3388b34154ac70d2a3fa49caca725cb85a Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 27 Mar 2024 19:23:16 +0000 Subject: [PATCH] You can now harvest pinecones and acorns from spruce and oak leaves using a hoe --- .../unicopia/InteractionManager.java | 6 ++ .../client/ClientInteractionManager.java | 7 ++ .../unicopia/item/ForageableItem.java | 93 +++++++++++++++++++ .../minelittlepony/unicopia/item/UItems.java | 5 +- 4 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/item/ForageableItem.java diff --git a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java index 7c60d0d5..e0848e1a 100644 --- a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java @@ -14,6 +14,8 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.PacketByteBuf; import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.world.World; public class InteractionManager { @@ -90,4 +92,8 @@ public class InteractionManager { public void sendPlayerLookAngles(PlayerEntity player) { } + + public void addBlockBreakingParticles(BlockPos pos, Direction direction) { + + } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java b/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java index 837b65fd..13352054 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/client/ClientInteractionManager.java @@ -41,6 +41,8 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; import net.minecraft.sound.SoundCategory; import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.random.Random; import net.minecraft.world.World; @@ -161,4 +163,9 @@ public class ClientInteractionManager extends InteractionManager { c.networkHandler.sendPacket(new PlayerMoveC2SPacket.LookAndOnGround(player.getYaw(), player.getPitch(), player.isOnGround())); } } + + @Override + public void addBlockBreakingParticles(BlockPos pos, Direction direction) { + client.particleManager.addBlockBreakingParticles(pos, direction); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/ForageableItem.java b/src/main/java/com/minelittlepony/unicopia/item/ForageableItem.java new file mode 100644 index 00000000..bb129cf6 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/ForageableItem.java @@ -0,0 +1,93 @@ +package com.minelittlepony.unicopia.item; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import com.minelittlepony.unicopia.InteractionManager; +import com.minelittlepony.unicopia.item.enchantment.EnchantmentUtil; +import com.minelittlepony.unicopia.server.world.BlockDestructionManager; + +import net.fabricmc.fabric.api.event.player.UseBlockCallback; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.HoeItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ToolMaterials; +import net.minecraft.registry.tag.BlockTags; +import net.minecraft.registry.tag.ItemTags; +import net.minecraft.sound.SoundCategory; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.WorldEvents; + +public class ForageableItem extends Item { + private static final List REGISTRY = new ArrayList<>(); + static { + UseBlockCallback.EVENT.register((PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) -> { + if (player.shouldCancelInteraction()) { + return ActionResult.PASS; + } + + ItemStack stack = player.getStackInHand(hand); + if (!stack.isIn(ItemTags.HOES)) { + return ActionResult.PASS; + } + + BlockPos pos = hitResult.getBlockPos(); + BlockState state = world.getBlockState(pos); + + ActionResult result = ActionResult.PASS; + + if (state.isIn(BlockTags.LEAVES)) { + player.swingHand(hand); + world.playSound(player, pos, state.getSoundGroup().getHitSound(), SoundCategory.BLOCKS); + InteractionManager.instance().addBlockBreakingParticles(pos, hitResult.getSide()); + + int miningLevel = (stack.getItem() instanceof HoeItem hoe ? hoe.getMaterial().getMiningLevel() : 59); + + for (ForageableItem item : REGISTRY) { + if ((result = item.onTryForage(world, pos, state, stack, player, miningLevel)).isAccepted()) { + stack.damage(1, player, p -> p.sendToolBreakStatus(hand)); + return result; + } + } + } + + return result.isAccepted() ? ActionResult.SUCCESS : ActionResult.PASS; + }); + } + + private final Supplier targetBlock; + + public ForageableItem(Settings settings, Supplier targetBlock) { + super(settings); + this.targetBlock = targetBlock; + REGISTRY.add(this); + } + + public ActionResult onTryForage(World world, BlockPos pos, BlockState state, ItemStack stack, PlayerEntity player, int miningLevel) { + if (state.isOf(targetBlock.get())) { + int spawnChance = (int)((1F - MathHelper.clamp(miningLevel / (float)ToolMaterials.NETHERITE.getMiningLevel(), 0, 1)) * 32); + spawnChance -= EnchantmentUtil.getLuck(1, player); + + if (spawnChance <= 0 || world.random.nextInt(spawnChance) == 0) { + Block.dropStack(world, pos, new ItemStack(this, 1 + EnchantmentHelper.getLooting(player))); + world.syncWorldEvent(WorldEvents.BLOCK_BROKEN, pos, Block.getRawIdFromState(state)); + if (BlockDestructionManager.of(world).damageBlock(pos, world.getRandom().nextBetween(3, 7)) >= BlockDestructionManager.MAX_DAMAGE) { + world.breakBlock(pos, true); + } + return ActionResult.SUCCESS; + } + return ActionResult.FAIL; + } + return ActionResult.PASS; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/item/UItems.java b/src/main/java/com/minelittlepony/unicopia/item/UItems.java index b75f9a6f..0c8fdaab 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/item/UItems.java @@ -16,6 +16,7 @@ import com.terraformersmc.terraform.boat.api.TerraformBoatType; import com.terraformersmc.terraform.boat.api.TerraformBoatTypeRegistry; import com.terraformersmc.terraform.boat.api.item.TerraformBoatItemHelper; +import net.minecraft.block.Blocks; import net.minecraft.entity.attribute.EntityAttributeModifier; import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.vehicle.BoatEntity; @@ -85,8 +86,8 @@ public interface UItems { Item WHEAT_WORMS = register("wheat_worms", new Item(new Item.Settings().maxCount(16).food(UFoodComponents.WORMS)), ItemGroups.NATURAL); Item MUFFIN = register("muffin", new MuffinItem(new Item.Settings().maxCount(32).food(FoodComponents.BREAD), 0), ItemGroups.FOOD_AND_DRINK); - Item PINECONE = register("pinecone", new Item(new Item.Settings().food(UFoodComponents.PINECONE).maxCount(3)), ItemGroups.FOOD_AND_DRINK); - Item ACORN = register("acorn", new Item(new Item.Settings().food(UFoodComponents.ACORN).maxCount(16)), ItemGroups.FOOD_AND_DRINK); + Item PINECONE = register("pinecone", new ForageableItem(new Item.Settings().food(UFoodComponents.PINECONE).maxCount(16), () -> Blocks.SPRUCE_LEAVES), ItemGroups.FOOD_AND_DRINK); + Item ACORN = register("acorn", new ForageableItem(new Item.Settings().food(UFoodComponents.ACORN).maxCount(16), () -> Blocks.OAK_LEAVES), ItemGroups.FOOD_AND_DRINK); Item MANGO = register("mango", new Item(new Item.Settings().food(UFoodComponents.MANGO)), ItemGroups.FOOD_AND_DRINK); Item BANANA = register("banana", new Item(new Item.Settings().food(UFoodComponents.BANANA)), ItemGroups.FOOD_AND_DRINK); Item CURING_JOKE = register("curing_joke", new CuringJokeItem(UBlocks.CURING_JOKE, new Item.Settings().food(UFoodComponents.POISON_JOKE)), ItemGroups.NATURAL);