322 lines
15 KiB
Java
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) {
|
|
}
|
|
}
|