package net.minecraft.world.item; import java.util.Collection; import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.component.DebugStickState; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.Property; import org.jetbrains.annotations.Nullable; public class DebugStickItem extends Item { public DebugStickItem(Item.Properties properties) { super(properties); } @Override public boolean canDestroyBlock(ItemStack stack, BlockState state, Level level, BlockPos pos, LivingEntity entity) { if (!level.isClientSide && entity instanceof Player player) { this.handleInteraction(player, state, level, pos, false, stack); } return false; } @Override public InteractionResult useOn(UseOnContext context) { Player player = context.getPlayer(); Level level = context.getLevel(); if (!level.isClientSide && player != null) { BlockPos blockPos = context.getClickedPos(); if (!this.handleInteraction(player, level.getBlockState(blockPos), level, blockPos, true, context.getItemInHand())) { return InteractionResult.FAIL; } } return InteractionResult.SUCCESS; } private boolean handleInteraction(Player player, BlockState stateClicked, LevelAccessor accessor, BlockPos pos, boolean shouldCycleState, ItemStack debugStack) { if (!player.canUseGameMasterBlocks()) { return false; } else { Holder holder = stateClicked.getBlockHolder(); StateDefinition stateDefinition = holder.value().getStateDefinition(); Collection> collection = stateDefinition.getProperties(); if (collection.isEmpty()) { message(player, Component.translatable(this.descriptionId + ".empty", holder.getRegisteredName())); return false; } else { DebugStickState debugStickState = debugStack.get(DataComponents.DEBUG_STICK_STATE); if (debugStickState == null) { return false; } else { Property property = (Property)debugStickState.properties().get(holder); if (shouldCycleState) { if (property == null) { property = (Property)collection.iterator().next(); } BlockState blockState = cycleState(stateClicked, property, player.isSecondaryUseActive()); accessor.setBlock(pos, blockState, 18); message(player, Component.translatable(this.descriptionId + ".update", property.getName(), getNameHelper(blockState, property))); } else { property = getRelative(collection, property, player.isSecondaryUseActive()); debugStack.set(DataComponents.DEBUG_STICK_STATE, debugStickState.withProperty(holder, property)); message(player, Component.translatable(this.descriptionId + ".select", property.getName(), getNameHelper(stateClicked, property))); } return true; } } } } private static > BlockState cycleState(BlockState state, Property property, boolean backwards) { return state.setValue(property, getRelative(property.getPossibleValues(), state.getValue(property), backwards)); } private static T getRelative(Iterable allowedValues, @Nullable T currentValue, boolean backwards) { return backwards ? Util.findPreviousInIterable(allowedValues, currentValue) : Util.findNextInIterable(allowedValues, currentValue); } private static void message(Player player, Component messageComponent) { ((ServerPlayer)player).sendSystemMessage(messageComponent, true); } private static > String getNameHelper(BlockState state, Property property) { return property.getName(state.getValue(property)); } }