minecraft-src/net/minecraft/world/item/BlockItem.java
2025-07-04 03:45:38 +03:00

224 lines
8.3 KiB
Java

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<Block, Item> 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();
}
}