minecraft-src/net/minecraft/core/cauldron/CauldronInteraction.java
2025-07-04 03:45:38 +03:00

322 lines
15 KiB
Java

package net.minecraft.core.cauldron;
import com.mojang.serialization.Codec;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.util.Map;
import java.util.function.Predicate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.Stats;
import net.minecraft.tags.FluidTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ItemUtils;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.PotionContents;
import net.minecraft.world.item.alchemy.Potions;
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.LayeredCauldronBlock;
import net.minecraft.world.level.block.ShulkerBoxBlock;
import net.minecraft.world.level.block.entity.BannerPatternLayers;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.material.FluidState;
public interface CauldronInteraction {
Map<String, CauldronInteraction.InteractionMap> INTERACTIONS = new Object2ObjectArrayMap<>();
Codec<CauldronInteraction.InteractionMap> CODEC = Codec.stringResolver(CauldronInteraction.InteractionMap::name, INTERACTIONS::get);
CauldronInteraction.InteractionMap EMPTY = newInteractionMap("empty");
CauldronInteraction.InteractionMap WATER = newInteractionMap("water");
CauldronInteraction.InteractionMap LAVA = newInteractionMap("lava");
CauldronInteraction.InteractionMap POWDER_SNOW = newInteractionMap("powder_snow");
static CauldronInteraction.InteractionMap newInteractionMap(String name) {
Object2ObjectOpenHashMap<Item, CauldronInteraction> object2ObjectOpenHashMap = new Object2ObjectOpenHashMap<>();
object2ObjectOpenHashMap.defaultReturnValue((blockState, level, blockPos, player, interactionHand, itemStack) -> InteractionResult.TRY_WITH_EMPTY_HAND);
CauldronInteraction.InteractionMap interactionMap = new CauldronInteraction.InteractionMap(name, object2ObjectOpenHashMap);
INTERACTIONS.put(name, interactionMap);
return interactionMap;
}
InteractionResult interact(BlockState blockState, Level level, BlockPos blockPos, Player player, InteractionHand interactionHand, ItemStack itemStack);
static void bootStrap() {
Map<Item, CauldronInteraction> map = EMPTY.map();
addDefaultInteractions(map);
map.put(Items.POTION, (CauldronInteraction)(blockState, level, blockPos, player, interactionHand, itemStack) -> {
PotionContents potionContents = itemStack.get(DataComponents.POTION_CONTENTS);
if (potionContents != null && potionContents.is(Potions.WATER)) {
if (!level.isClientSide) {
Item item = itemStack.getItem();
player.setItemInHand(interactionHand, ItemUtils.createFilledResult(itemStack, player, new ItemStack(Items.GLASS_BOTTLE)));
player.awardStat(Stats.USE_CAULDRON);
player.awardStat(Stats.ITEM_USED.get(item));
level.setBlockAndUpdate(blockPos, Blocks.WATER_CAULDRON.defaultBlockState());
level.playSound(null, blockPos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.FLUID_PLACE, blockPos);
}
return InteractionResult.SUCCESS;
} else {
return InteractionResult.TRY_WITH_EMPTY_HAND;
}
});
Map<Item, CauldronInteraction> map2 = WATER.map();
addDefaultInteractions(map2);
map2.put(
Items.BUCKET,
(CauldronInteraction)(blockState, level, blockPos, player, interactionHand, itemStack) -> fillBucket(
blockState,
level,
blockPos,
player,
interactionHand,
itemStack,
new ItemStack(Items.WATER_BUCKET),
blockStatex -> (Integer)blockStatex.getValue(LayeredCauldronBlock.LEVEL) == 3,
SoundEvents.BUCKET_FILL
)
);
map2.put(Items.GLASS_BOTTLE, (CauldronInteraction)(blockState, level, blockPos, player, interactionHand, itemStack) -> {
if (!level.isClientSide) {
Item item = itemStack.getItem();
player.setItemInHand(interactionHand, ItemUtils.createFilledResult(itemStack, player, PotionContents.createItemStack(Items.POTION, Potions.WATER)));
player.awardStat(Stats.USE_CAULDRON);
player.awardStat(Stats.ITEM_USED.get(item));
LayeredCauldronBlock.lowerFillLevel(blockState, level, blockPos);
level.playSound(null, blockPos, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.FLUID_PICKUP, blockPos);
}
return InteractionResult.SUCCESS;
});
map2.put(Items.POTION, (CauldronInteraction)(blockState, level, blockPos, player, interactionHand, itemStack) -> {
if ((Integer)blockState.getValue(LayeredCauldronBlock.LEVEL) == 3) {
return InteractionResult.TRY_WITH_EMPTY_HAND;
} else {
PotionContents potionContents = itemStack.get(DataComponents.POTION_CONTENTS);
if (potionContents != null && potionContents.is(Potions.WATER)) {
if (!level.isClientSide) {
player.setItemInHand(interactionHand, ItemUtils.createFilledResult(itemStack, player, new ItemStack(Items.GLASS_BOTTLE)));
player.awardStat(Stats.USE_CAULDRON);
player.awardStat(Stats.ITEM_USED.get(itemStack.getItem()));
level.setBlockAndUpdate(blockPos, blockState.cycle(LayeredCauldronBlock.LEVEL));
level.playSound(null, blockPos, SoundEvents.BOTTLE_EMPTY, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.FLUID_PLACE, blockPos);
}
return InteractionResult.SUCCESS;
} else {
return InteractionResult.TRY_WITH_EMPTY_HAND;
}
}
});
map2.put(Items.LEATHER_BOOTS, CauldronInteraction::dyedItemIteration);
map2.put(Items.LEATHER_LEGGINGS, CauldronInteraction::dyedItemIteration);
map2.put(Items.LEATHER_CHESTPLATE, CauldronInteraction::dyedItemIteration);
map2.put(Items.LEATHER_HELMET, CauldronInteraction::dyedItemIteration);
map2.put(Items.LEATHER_HORSE_ARMOR, CauldronInteraction::dyedItemIteration);
map2.put(Items.WOLF_ARMOR, CauldronInteraction::dyedItemIteration);
map2.put(Items.WHITE_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.GRAY_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.BLACK_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.BLUE_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.BROWN_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.CYAN_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.GREEN_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.LIGHT_BLUE_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.LIGHT_GRAY_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.LIME_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.MAGENTA_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.ORANGE_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.PINK_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.PURPLE_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.RED_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.YELLOW_BANNER, CauldronInteraction::bannerInteraction);
map2.put(Items.WHITE_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.GRAY_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.BLACK_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.BLUE_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.BROWN_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.CYAN_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.GREEN_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.LIGHT_BLUE_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.LIGHT_GRAY_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.LIME_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.MAGENTA_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.ORANGE_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.PINK_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.PURPLE_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.RED_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
map2.put(Items.YELLOW_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
Map<Item, CauldronInteraction> map3 = LAVA.map();
map3.put(
Items.BUCKET,
(CauldronInteraction)(blockState, level, blockPos, player, interactionHand, itemStack) -> fillBucket(
blockState, level, blockPos, player, interactionHand, itemStack, new ItemStack(Items.LAVA_BUCKET), blockStatex -> true, SoundEvents.BUCKET_FILL_LAVA
)
);
addDefaultInteractions(map3);
Map<Item, CauldronInteraction> map4 = POWDER_SNOW.map();
map4.put(
Items.BUCKET,
(CauldronInteraction)(blockState, level, blockPos, player, interactionHand, itemStack) -> fillBucket(
blockState,
level,
blockPos,
player,
interactionHand,
itemStack,
new ItemStack(Items.POWDER_SNOW_BUCKET),
blockStatex -> (Integer)blockStatex.getValue(LayeredCauldronBlock.LEVEL) == 3,
SoundEvents.BUCKET_FILL_POWDER_SNOW
)
);
addDefaultInteractions(map4);
}
static void addDefaultInteractions(Map<Item, CauldronInteraction> interactionsMap) {
interactionsMap.put(Items.LAVA_BUCKET, CauldronInteraction::fillLavaInteraction);
interactionsMap.put(Items.WATER_BUCKET, CauldronInteraction::fillWaterInteraction);
interactionsMap.put(Items.POWDER_SNOW_BUCKET, CauldronInteraction::fillPowderSnowInteraction);
}
static InteractionResult fillBucket(
BlockState state,
Level level,
BlockPos pos,
Player player,
InteractionHand hand,
ItemStack emptyStack,
ItemStack filledStack,
Predicate<BlockState> statePredicate,
SoundEvent fillSound
) {
if (!statePredicate.test(state)) {
return InteractionResult.TRY_WITH_EMPTY_HAND;
} else {
if (!level.isClientSide) {
Item item = emptyStack.getItem();
player.setItemInHand(hand, ItemUtils.createFilledResult(emptyStack, player, filledStack));
player.awardStat(Stats.USE_CAULDRON);
player.awardStat(Stats.ITEM_USED.get(item));
level.setBlockAndUpdate(pos, Blocks.CAULDRON.defaultBlockState());
level.playSound(null, pos, fillSound, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.FLUID_PICKUP, pos);
}
return InteractionResult.SUCCESS;
}
}
static InteractionResult emptyBucket(
Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStackl, BlockState state, SoundEvent emptySound
) {
if (!level.isClientSide) {
Item item = filledStackl.getItem();
player.setItemInHand(hand, ItemUtils.createFilledResult(filledStackl, player, new ItemStack(Items.BUCKET)));
player.awardStat(Stats.FILL_CAULDRON);
player.awardStat(Stats.ITEM_USED.get(item));
level.setBlockAndUpdate(pos, state);
level.playSound(null, pos, emptySound, SoundSource.BLOCKS, 1.0F, 1.0F);
level.gameEvent(null, GameEvent.FLUID_PLACE, pos);
}
return InteractionResult.SUCCESS;
}
private static InteractionResult fillWaterInteraction(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStack) {
return emptyBucket(
level, pos, player, hand, filledStack, Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY
);
}
private static InteractionResult fillLavaInteraction(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStack) {
return (InteractionResult)(isUnderWater(level, pos)
? InteractionResult.CONSUME
: emptyBucket(level, pos, player, hand, filledStack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA));
}
private static InteractionResult fillPowderSnowInteraction(
BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack filledStack
) {
return (InteractionResult)(isUnderWater(level, pos)
? InteractionResult.CONSUME
: emptyBucket(
level,
pos,
player,
hand,
filledStack,
Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3),
SoundEvents.BUCKET_EMPTY_POWDER_SNOW
));
}
private static InteractionResult shulkerBoxInteraction(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack stack) {
Block block = Block.byItem(stack.getItem());
if (!(block instanceof ShulkerBoxBlock)) {
return InteractionResult.TRY_WITH_EMPTY_HAND;
} else {
if (!level.isClientSide) {
ItemStack itemStack = stack.transmuteCopy(Blocks.SHULKER_BOX, 1);
player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, itemStack, false));
player.awardStat(Stats.CLEAN_SHULKER_BOX);
LayeredCauldronBlock.lowerFillLevel(state, level, pos);
}
return InteractionResult.SUCCESS;
}
}
private static InteractionResult bannerInteraction(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack stack) {
BannerPatternLayers bannerPatternLayers = stack.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY);
if (bannerPatternLayers.layers().isEmpty()) {
return InteractionResult.TRY_WITH_EMPTY_HAND;
} else {
if (!level.isClientSide) {
ItemStack itemStack = stack.copyWithCount(1);
itemStack.set(DataComponents.BANNER_PATTERNS, bannerPatternLayers.removeLast());
player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, itemStack, false));
player.awardStat(Stats.CLEAN_BANNER);
LayeredCauldronBlock.lowerFillLevel(state, level, pos);
}
return InteractionResult.SUCCESS;
}
}
private static InteractionResult dyedItemIteration(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack stack) {
if (!stack.is(ItemTags.DYEABLE)) {
return InteractionResult.TRY_WITH_EMPTY_HAND;
} else if (!stack.has(DataComponents.DYED_COLOR)) {
return InteractionResult.TRY_WITH_EMPTY_HAND;
} else {
if (!level.isClientSide) {
stack.remove(DataComponents.DYED_COLOR);
player.awardStat(Stats.CLEAN_ARMOR);
LayeredCauldronBlock.lowerFillLevel(state, level, pos);
}
return InteractionResult.SUCCESS;
}
}
private static boolean isUnderWater(Level level, BlockPos pos) {
FluidState fluidState = level.getFluidState(pos.above());
return fluidState.is(FluidTags.WATER);
}
public record InteractionMap(String name, Map<Item, CauldronInteraction> map) {
}
}