package net.minecraft.world.item; import java.util.Map; import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.core.BlockPos; import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.item.component.BlockItemStateProperties; import net.minecraft.world.item.component.CustomData; import net.minecraft.world.item.component.ItemContainerContents; import net.minecraft.world.item.context.BlockPlaceContext; 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.ShulkerBoxBlock; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.gameevent.GameEvent.Context; import net.minecraft.world.phys.shapes.CollisionContext; import org.jetbrains.annotations.Nullable; public class BlockItem extends Item { @Deprecated private final Block block; public BlockItem(Block block, Item.Properties properties) { super(properties); this.block = block; } @Override public InteractionResult useOn(UseOnContext context) { InteractionResult interactionResult = this.place(new BlockPlaceContext(context)); return !interactionResult.consumesAction() && context.getItemInHand().has(DataComponents.CONSUMABLE) ? super.use(context.getLevel(), context.getPlayer(), context.getHand()) : interactionResult; } public InteractionResult place(BlockPlaceContext context) { if (!this.getBlock().isEnabled(context.getLevel().enabledFeatures())) { return InteractionResult.FAIL; } else if (!context.canPlace()) { return InteractionResult.FAIL; } else { BlockPlaceContext blockPlaceContext = this.updatePlacementContext(context); if (blockPlaceContext == null) { return InteractionResult.FAIL; } else { BlockState blockState = this.getPlacementState(blockPlaceContext); if (blockState == null) { return InteractionResult.FAIL; } else if (!this.placeBlock(blockPlaceContext, blockState)) { return InteractionResult.FAIL; } else { BlockPos blockPos = blockPlaceContext.getClickedPos(); Level level = blockPlaceContext.getLevel(); Player player = blockPlaceContext.getPlayer(); ItemStack itemStack = blockPlaceContext.getItemInHand(); BlockState blockState2 = level.getBlockState(blockPos); if (blockState2.is(blockState.getBlock())) { blockState2 = this.updateBlockStateFromTag(blockPos, level, itemStack, blockState2); this.updateCustomBlockEntityTag(blockPos, level, player, itemStack, blockState2); updateBlockEntityComponents(level, blockPos, itemStack); blockState2.getBlock().setPlacedBy(level, blockPos, blockState2, player, itemStack); if (player instanceof ServerPlayer) { CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer)player, blockPos, itemStack); } } SoundType soundType = blockState2.getSoundType(); level.playSound(player, blockPos, this.getPlaceSound(blockState2), SoundSource.BLOCKS, (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F); level.gameEvent(GameEvent.BLOCK_PLACE, blockPos, Context.of(player, blockState2)); itemStack.consume(1, player); return InteractionResult.SUCCESS; } } } } protected SoundEvent getPlaceSound(BlockState state) { return state.getSoundType().getPlaceSound(); } @Nullable public BlockPlaceContext updatePlacementContext(BlockPlaceContext context) { return context; } private static void updateBlockEntityComponents(Level level, BlockPos poa, ItemStack stack) { BlockEntity blockEntity = level.getBlockEntity(poa); if (blockEntity != null) { blockEntity.applyComponentsFromItemStack(stack); blockEntity.setChanged(); } } protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, @Nullable Player player, ItemStack stack, BlockState state) { return updateCustomBlockEntityTag(level, player, pos, stack); } @Nullable protected BlockState getPlacementState(BlockPlaceContext context) { BlockState blockState = this.getBlock().getStateForPlacement(context); return blockState != null && this.canPlace(context, blockState) ? blockState : null; } private BlockState updateBlockStateFromTag(BlockPos pos, Level level, ItemStack stack, BlockState state) { BlockItemStateProperties blockItemStateProperties = stack.getOrDefault(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY); if (blockItemStateProperties.isEmpty()) { return state; } else { BlockState blockState = blockItemStateProperties.apply(state); if (blockState != state) { level.setBlock(pos, blockState, 2); } return blockState; } } protected boolean canPlace(BlockPlaceContext context, BlockState state) { Player player = context.getPlayer(); return (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), CollisionContext.placementContext(player)); } protected boolean mustSurvive() { return true; } protected boolean placeBlock(BlockPlaceContext context, BlockState state) { return context.getLevel().setBlock(context.getClickedPos(), state, 11); } public static boolean updateCustomBlockEntityTag(Level level, @Nullable Player player, BlockPos pos, ItemStack stack) { if (level.isClientSide) { return false; } else { CustomData customData = stack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); if (!customData.isEmpty()) { BlockEntityType blockEntityType = customData.parseEntityType(level.registryAccess(), Registries.BLOCK_ENTITY_TYPE); if (blockEntityType == null) { return false; } BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity != null) { BlockEntityType blockEntityType2 = blockEntity.getType(); if (blockEntityType2 != blockEntityType) { return false; } if (!blockEntityType2.onlyOpCanSetNbt() || player != null && player.canUseGameMasterBlocks()) { return customData.loadInto(blockEntity, level.registryAccess()); } return false; } } return false; } } @Override public boolean shouldPrintOpWarning(ItemStack stack, @Nullable Player player) { if (player != null && player.getPermissionLevel() >= 2) { CustomData customData = stack.get(DataComponents.BLOCK_ENTITY_DATA); if (customData != null) { BlockEntityType blockEntityType = customData.parseEntityType(player.level().registryAccess(), Registries.BLOCK_ENTITY_TYPE); return blockEntityType != null && blockEntityType.onlyOpCanSetNbt(); } } return false; } public Block getBlock() { return this.block; } public void registerBlocks(Map blockToItemMap, Item item) { blockToItemMap.put(this.getBlock(), item); } @Override public boolean canFitInsideContainerItems() { return !(this.getBlock() instanceof ShulkerBoxBlock); } @Override public void onDestroyed(ItemEntity itemEntity) { ItemContainerContents itemContainerContents = itemEntity.getItem().set(DataComponents.CONTAINER, ItemContainerContents.EMPTY); if (itemContainerContents != null) { ItemUtils.onContainerDestroyed(itemEntity, itemContainerContents.nonEmptyItemsCopy()); } } public static void setBlockEntityData(ItemStack stack, BlockEntityType blockEntityType, CompoundTag blockEntityData) { blockEntityData.remove("id"); if (blockEntityData.isEmpty()) { stack.remove(DataComponents.BLOCK_ENTITY_DATA); } else { BlockEntity.addEntityType(blockEntityData, blockEntityType); stack.set(DataComponents.BLOCK_ENTITY_DATA, CustomData.of(blockEntityData)); } } @Override public FeatureFlagSet requiredFeatures() { return this.getBlock().requiredFeatures(); } }