223 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
	
		
			8.2 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.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.storage.TagValueOutput;
 | |
| 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, GameEvent.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, TagValueOutput output) {
 | |
| 		output.discard("id");
 | |
| 		if (output.isEmpty()) {
 | |
| 			stack.remove(DataComponents.BLOCK_ENTITY_DATA);
 | |
| 		} else {
 | |
| 			BlockEntity.addEntityType(output, blockEntityType);
 | |
| 			stack.set(DataComponents.BLOCK_ENTITY_DATA, CustomData.of(output.buildResult()));
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public FeatureFlagSet requiredFeatures() {
 | |
| 		return this.getBlock().requiredFeatures();
 | |
| 	}
 | |
| }
 |