package net.minecraft.world.item; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.mojang.datafixers.util.Pair; import java.util.Map; import java.util.function.Consumer; import java.util.function.Predicate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.ItemLike; 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.gameevent.GameEvent; import net.minecraft.world.level.gameevent.GameEvent.Context; public class HoeItem extends Item { protected static final Map, Consumer>> TILLABLES = Maps., Consumer>>newHashMap( ImmutableMap.of( Blocks.GRASS_BLOCK, Pair.of(HoeItem::onlyIfAirAbove, changeIntoState(Blocks.FARMLAND.defaultBlockState())), Blocks.DIRT_PATH, Pair.of(HoeItem::onlyIfAirAbove, changeIntoState(Blocks.FARMLAND.defaultBlockState())), Blocks.DIRT, Pair.of(HoeItem::onlyIfAirAbove, changeIntoState(Blocks.FARMLAND.defaultBlockState())), Blocks.COARSE_DIRT, Pair.of(HoeItem::onlyIfAirAbove, changeIntoState(Blocks.DIRT.defaultBlockState())), Blocks.ROOTED_DIRT, Pair.of(useOnContext -> true, changeIntoStateAndDropItem(Blocks.DIRT.defaultBlockState(), Items.HANGING_ROOTS)) ) ); public HoeItem(ToolMaterial material, float attackDamage, float attackSpeed, Item.Properties properties) { super(properties.hoe(material, attackDamage, attackSpeed)); } @Override public InteractionResult useOn(UseOnContext context) { Level level = context.getLevel(); BlockPos blockPos = context.getClickedPos(); Pair, Consumer> pair = (Pair, Consumer>)TILLABLES.get( level.getBlockState(blockPos).getBlock() ); if (pair == null) { return InteractionResult.PASS; } else { Predicate predicate = pair.getFirst(); Consumer consumer = pair.getSecond(); if (predicate.test(context)) { Player player = context.getPlayer(); level.playSound(player, blockPos, SoundEvents.HOE_TILL, SoundSource.BLOCKS, 1.0F, 1.0F); if (!level.isClientSide) { consumer.accept(context); if (player != null) { context.getItemInHand().hurtAndBreak(1, player, LivingEntity.getSlotForHand(context.getHand())); } } return InteractionResult.SUCCESS; } else { return InteractionResult.PASS; } } } public static Consumer changeIntoState(BlockState state) { return useOnContext -> { useOnContext.getLevel().setBlock(useOnContext.getClickedPos(), state, 11); useOnContext.getLevel().gameEvent(GameEvent.BLOCK_CHANGE, useOnContext.getClickedPos(), Context.of(useOnContext.getPlayer(), state)); }; } public static Consumer changeIntoStateAndDropItem(BlockState state, ItemLike itemToDrop) { return useOnContext -> { useOnContext.getLevel().setBlock(useOnContext.getClickedPos(), state, 11); useOnContext.getLevel().gameEvent(GameEvent.BLOCK_CHANGE, useOnContext.getClickedPos(), Context.of(useOnContext.getPlayer(), state)); Block.popResourceFromFace(useOnContext.getLevel(), useOnContext.getClickedPos(), useOnContext.getClickedFace(), new ItemStack(itemToDrop)); }; } public static boolean onlyIfAirAbove(UseOnContext context) { return context.getClickedFace() != Direction.DOWN && context.getLevel().getBlockState(context.getClickedPos().above()).isAir(); } }