350 lines
16 KiB
Java
350 lines
16 KiB
Java
package net.minecraft.world.level.block;
|
|
|
|
import com.mojang.serialization.MapCodec;
|
|
import java.util.List;
|
|
import java.util.function.BiConsumer;
|
|
import javax.annotation.Nullable;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.advancements.CriteriaTriggers;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.component.DataComponents;
|
|
import net.minecraft.core.particles.ParticleTypes;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.sounds.SoundEvents;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.stats.Stats;
|
|
import net.minecraft.tags.BlockTags;
|
|
import net.minecraft.tags.EnchantmentTags;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.Containers;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.animal.Bee;
|
|
import net.minecraft.world.entity.boss.wither.WitherBoss;
|
|
import net.minecraft.world.entity.item.ItemEntity;
|
|
import net.minecraft.world.entity.item.PrimedTnt;
|
|
import net.minecraft.world.entity.monster.Creeper;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.entity.projectile.WitherSkull;
|
|
import net.minecraft.world.entity.vehicle.MinecartTNT;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.item.component.BlockItemStateProperties;
|
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
|
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
|
import net.minecraft.world.level.Explosion;
|
|
import net.minecraft.world.level.GameRules;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.LevelReader;
|
|
import net.minecraft.world.level.ScheduledTickAccess;
|
|
import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.StateDefinition;
|
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
|
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
|
import net.minecraft.world.level.gameevent.GameEvent;
|
|
import net.minecraft.world.level.storage.loot.LootParams;
|
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
|
import net.minecraft.world.phys.AABB;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
|
|
|
public class BeehiveBlock extends BaseEntityBlock {
|
|
public static final MapCodec<BeehiveBlock> CODEC = simpleCodec(BeehiveBlock::new);
|
|
public static final EnumProperty<Direction> FACING = HorizontalDirectionalBlock.FACING;
|
|
public static final IntegerProperty HONEY_LEVEL = BlockStateProperties.LEVEL_HONEY;
|
|
public static final int MAX_HONEY_LEVELS = 5;
|
|
private static final int SHEARED_HONEYCOMB_COUNT = 3;
|
|
|
|
@Override
|
|
public MapCodec<BeehiveBlock> codec() {
|
|
return CODEC;
|
|
}
|
|
|
|
public BeehiveBlock(BlockBehaviour.Properties p_49568_) {
|
|
super(p_49568_);
|
|
this.registerDefaultState(this.stateDefinition.any().setValue(HONEY_LEVEL, 0).setValue(FACING, Direction.NORTH));
|
|
}
|
|
|
|
@Override
|
|
protected boolean hasAnalogOutputSignal(BlockState p_49618_) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
protected int getAnalogOutputSignal(BlockState p_49620_, Level p_49621_, BlockPos p_49622_) {
|
|
return p_49620_.getValue(HONEY_LEVEL);
|
|
}
|
|
|
|
@Override
|
|
public void playerDestroy(Level p_49584_, Player p_49585_, BlockPos p_49586_, BlockState p_49587_, @Nullable BlockEntity p_49588_, ItemStack p_49589_) {
|
|
super.playerDestroy(p_49584_, p_49585_, p_49586_, p_49587_, p_49588_, p_49589_);
|
|
if (!p_49584_.isClientSide && p_49588_ instanceof BeehiveBlockEntity beehiveblockentity) {
|
|
if (!EnchantmentHelper.hasTag(p_49589_, EnchantmentTags.PREVENTS_BEE_SPAWNS_WHEN_MINING)) {
|
|
beehiveblockentity.emptyAllLivingFromHive(p_49585_, p_49587_, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY);
|
|
Containers.updateNeighboursAfterDestroy(p_49587_, p_49584_, p_49586_);
|
|
this.angerNearbyBees(p_49584_, p_49586_);
|
|
}
|
|
|
|
CriteriaTriggers.BEE_NEST_DESTROYED.trigger((ServerPlayer)p_49585_, p_49587_, p_49589_, beehiveblockentity.getOccupantCount());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onExplosionHit(BlockState p_365385_, ServerLevel p_361160_, BlockPos p_363432_, Explosion p_364892_, BiConsumer<ItemStack, BlockPos> p_361789_) {
|
|
super.onExplosionHit(p_365385_, p_361160_, p_363432_, p_364892_, p_361789_);
|
|
this.angerNearbyBees(p_361160_, p_363432_);
|
|
}
|
|
|
|
private void angerNearbyBees(Level p_49650_, BlockPos p_49651_) {
|
|
AABB aabb = new AABB(p_49651_).inflate(8.0, 6.0, 8.0);
|
|
List<Bee> list = p_49650_.getEntitiesOfClass(Bee.class, aabb);
|
|
if (!list.isEmpty()) {
|
|
List<Player> list1 = p_49650_.getEntitiesOfClass(Player.class, aabb);
|
|
if (list1.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
for (Bee bee : list) {
|
|
if (bee.getTarget() == null) {
|
|
Player player = Util.getRandom(list1, p_49650_.random);
|
|
bee.setTarget(player);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void dropHoneycomb(Level p_49601_, BlockPos p_49602_) {
|
|
popResource(p_49601_, p_49602_, new ItemStack(Items.HONEYCOMB, 3));
|
|
}
|
|
|
|
@Override
|
|
protected InteractionResult useItemOn(
|
|
ItemStack p_331014_, BlockState p_328141_, Level p_329187_, BlockPos p_335985_, Player p_336201_, InteractionHand p_333071_, BlockHitResult p_331246_
|
|
) {
|
|
int i = p_328141_.getValue(HONEY_LEVEL);
|
|
boolean flag = false;
|
|
if (i >= 5) {
|
|
Item item = p_331014_.getItem();
|
|
if (p_331014_.is(Items.SHEARS)) {
|
|
p_329187_.playSound(
|
|
p_336201_, p_336201_.getX(), p_336201_.getY(), p_336201_.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.BLOCKS, 1.0F, 1.0F
|
|
);
|
|
dropHoneycomb(p_329187_, p_335985_);
|
|
p_331014_.hurtAndBreak(1, p_336201_, LivingEntity.getSlotForHand(p_333071_));
|
|
flag = true;
|
|
p_329187_.gameEvent(p_336201_, GameEvent.SHEAR, p_335985_);
|
|
} else if (p_331014_.is(Items.GLASS_BOTTLE)) {
|
|
p_331014_.shrink(1);
|
|
p_329187_.playSound(
|
|
p_336201_, p_336201_.getX(), p_336201_.getY(), p_336201_.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F
|
|
);
|
|
if (p_331014_.isEmpty()) {
|
|
p_336201_.setItemInHand(p_333071_, new ItemStack(Items.HONEY_BOTTLE));
|
|
} else if (!p_336201_.getInventory().add(new ItemStack(Items.HONEY_BOTTLE))) {
|
|
p_336201_.drop(new ItemStack(Items.HONEY_BOTTLE), false);
|
|
}
|
|
|
|
flag = true;
|
|
p_329187_.gameEvent(p_336201_, GameEvent.FLUID_PICKUP, p_335985_);
|
|
}
|
|
|
|
if (!p_329187_.isClientSide() && flag) {
|
|
p_336201_.awardStat(Stats.ITEM_USED.get(item));
|
|
}
|
|
}
|
|
|
|
if (flag) {
|
|
if (!CampfireBlock.isSmokeyPos(p_329187_, p_335985_)) {
|
|
if (this.hiveContainsBees(p_329187_, p_335985_)) {
|
|
this.angerNearbyBees(p_329187_, p_335985_);
|
|
}
|
|
|
|
this.releaseBeesAndResetHoneyLevel(p_329187_, p_328141_, p_335985_, p_336201_, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY);
|
|
} else {
|
|
this.resetHoneyLevel(p_329187_, p_328141_, p_335985_);
|
|
}
|
|
|
|
return InteractionResult.SUCCESS;
|
|
} else {
|
|
return super.useItemOn(p_331014_, p_328141_, p_329187_, p_335985_, p_336201_, p_333071_, p_331246_);
|
|
}
|
|
}
|
|
|
|
private boolean hiveContainsBees(Level p_49655_, BlockPos p_49656_) {
|
|
return p_49655_.getBlockEntity(p_49656_) instanceof BeehiveBlockEntity beehiveblockentity ? !beehiveblockentity.isEmpty() : false;
|
|
}
|
|
|
|
public void releaseBeesAndResetHoneyLevel(Level p_49595_, BlockState p_49596_, BlockPos p_49597_, @Nullable Player p_49598_, BeehiveBlockEntity.BeeReleaseStatus p_49599_) {
|
|
this.resetHoneyLevel(p_49595_, p_49596_, p_49597_);
|
|
if (p_49595_.getBlockEntity(p_49597_) instanceof BeehiveBlockEntity beehiveblockentity) {
|
|
beehiveblockentity.emptyAllLivingFromHive(p_49598_, p_49596_, p_49599_);
|
|
}
|
|
}
|
|
|
|
public void resetHoneyLevel(Level p_49591_, BlockState p_49592_, BlockPos p_49593_) {
|
|
p_49591_.setBlock(p_49593_, p_49592_.setValue(HONEY_LEVEL, 0), 3);
|
|
}
|
|
|
|
@Override
|
|
public void animateTick(BlockState p_220773_, Level p_220774_, BlockPos p_220775_, RandomSource p_220776_) {
|
|
if (p_220773_.getValue(HONEY_LEVEL) >= 5) {
|
|
for (int i = 0; i < p_220776_.nextInt(1) + 1; i++) {
|
|
this.trySpawnDripParticles(p_220774_, p_220775_, p_220773_);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void trySpawnDripParticles(Level p_49604_, BlockPos p_49605_, BlockState p_49606_) {
|
|
if (p_49606_.getFluidState().isEmpty() && !(p_49604_.random.nextFloat() < 0.3F)) {
|
|
VoxelShape voxelshape = p_49606_.getCollisionShape(p_49604_, p_49605_);
|
|
double d0 = voxelshape.max(Direction.Axis.Y);
|
|
if (d0 >= 1.0 && !p_49606_.is(BlockTags.IMPERMEABLE)) {
|
|
double d1 = voxelshape.min(Direction.Axis.Y);
|
|
if (d1 > 0.0) {
|
|
this.spawnParticle(p_49604_, p_49605_, voxelshape, p_49605_.getY() + d1 - 0.05);
|
|
} else {
|
|
BlockPos blockpos = p_49605_.below();
|
|
BlockState blockstate = p_49604_.getBlockState(blockpos);
|
|
VoxelShape voxelshape1 = blockstate.getCollisionShape(p_49604_, blockpos);
|
|
double d2 = voxelshape1.max(Direction.Axis.Y);
|
|
if ((d2 < 1.0 || !blockstate.isCollisionShapeFullBlock(p_49604_, blockpos)) && blockstate.getFluidState().isEmpty()) {
|
|
this.spawnParticle(p_49604_, p_49605_, voxelshape, p_49605_.getY() - 0.05);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void spawnParticle(Level p_49613_, BlockPos p_49614_, VoxelShape p_49615_, double p_49616_) {
|
|
this.spawnFluidParticle(
|
|
p_49613_,
|
|
p_49614_.getX() + p_49615_.min(Direction.Axis.X),
|
|
p_49614_.getX() + p_49615_.max(Direction.Axis.X),
|
|
p_49614_.getZ() + p_49615_.min(Direction.Axis.Z),
|
|
p_49614_.getZ() + p_49615_.max(Direction.Axis.Z),
|
|
p_49616_
|
|
);
|
|
}
|
|
|
|
private void spawnFluidParticle(Level p_49577_, double p_49578_, double p_49579_, double p_49580_, double p_49581_, double p_49582_) {
|
|
p_49577_.addParticle(
|
|
ParticleTypes.DRIPPING_HONEY,
|
|
Mth.lerp(p_49577_.random.nextDouble(), p_49578_, p_49579_),
|
|
p_49582_,
|
|
Mth.lerp(p_49577_.random.nextDouble(), p_49580_, p_49581_),
|
|
0.0,
|
|
0.0,
|
|
0.0
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public BlockState getStateForPlacement(BlockPlaceContext p_49573_) {
|
|
return this.defaultBlockState().setValue(FACING, p_49573_.getHorizontalDirection().getOpposite());
|
|
}
|
|
|
|
@Override
|
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_49646_) {
|
|
p_49646_.add(HONEY_LEVEL, FACING);
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public BlockEntity newBlockEntity(BlockPos p_152184_, BlockState p_152185_) {
|
|
return new BeehiveBlockEntity(p_152184_, p_152185_);
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level p_152180_, BlockState p_152181_, BlockEntityType<T> p_152182_) {
|
|
return p_152180_.isClientSide ? null : createTickerHelper(p_152182_, BlockEntityType.BEEHIVE, BeehiveBlockEntity::serverTick);
|
|
}
|
|
|
|
@Override
|
|
public BlockState playerWillDestroy(Level p_49608_, BlockPos p_49609_, BlockState p_49610_, Player p_49611_) {
|
|
if (p_49608_ instanceof ServerLevel serverlevel
|
|
&& p_49611_.preventsBlockDrops()
|
|
&& serverlevel.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)
|
|
&& p_49608_.getBlockEntity(p_49609_) instanceof BeehiveBlockEntity beehiveblockentity) {
|
|
int i = p_49610_.getValue(HONEY_LEVEL);
|
|
boolean flag = !beehiveblockentity.isEmpty();
|
|
if (flag || i > 0) {
|
|
ItemStack itemstack = new ItemStack(this);
|
|
itemstack.applyComponents(beehiveblockentity.collectComponents());
|
|
itemstack.set(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY.with(HONEY_LEVEL, i));
|
|
ItemEntity itementity = new ItemEntity(p_49608_, p_49609_.getX(), p_49609_.getY(), p_49609_.getZ(), itemstack);
|
|
itementity.setDefaultPickUpDelay();
|
|
p_49608_.addFreshEntity(itementity);
|
|
}
|
|
}
|
|
|
|
return super.playerWillDestroy(p_49608_, p_49609_, p_49610_, p_49611_);
|
|
}
|
|
|
|
@Override
|
|
protected List<ItemStack> getDrops(BlockState p_49636_, LootParams.Builder p_287581_) {
|
|
Entity entity = p_287581_.getOptionalParameter(LootContextParams.THIS_ENTITY);
|
|
if (entity instanceof PrimedTnt
|
|
|| entity instanceof Creeper
|
|
|| entity instanceof WitherSkull
|
|
|| entity instanceof WitherBoss
|
|
|| entity instanceof MinecartTNT) {
|
|
BlockEntity blockentity = p_287581_.getOptionalParameter(LootContextParams.BLOCK_ENTITY);
|
|
if (blockentity instanceof BeehiveBlockEntity beehiveblockentity) {
|
|
beehiveblockentity.emptyAllLivingFromHive(null, p_49636_, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY);
|
|
}
|
|
}
|
|
|
|
return super.getDrops(p_49636_, p_287581_);
|
|
}
|
|
|
|
@Override
|
|
protected ItemStack getCloneItemStack(LevelReader p_375896_, BlockPos p_377793_, BlockState p_377589_, boolean p_376286_) {
|
|
ItemStack itemstack = super.getCloneItemStack(p_375896_, p_377793_, p_377589_, p_376286_);
|
|
if (p_376286_) {
|
|
itemstack.set(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY.with(HONEY_LEVEL, p_377589_.getValue(HONEY_LEVEL)));
|
|
}
|
|
|
|
return itemstack;
|
|
}
|
|
|
|
@Override
|
|
protected BlockState updateShape(
|
|
BlockState p_49639_,
|
|
LevelReader p_364129_,
|
|
ScheduledTickAccess p_367483_,
|
|
BlockPos p_49643_,
|
|
Direction p_49640_,
|
|
BlockPos p_49644_,
|
|
BlockState p_49641_,
|
|
RandomSource p_365194_
|
|
) {
|
|
if (p_364129_.getBlockState(p_49644_).getBlock() instanceof FireBlock && p_364129_.getBlockEntity(p_49643_) instanceof BeehiveBlockEntity beehiveblockentity) {
|
|
beehiveblockentity.emptyAllLivingFromHive(null, p_49639_, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY);
|
|
}
|
|
|
|
return super.updateShape(p_49639_, p_364129_, p_367483_, p_49643_, p_49640_, p_49644_, p_49641_, p_365194_);
|
|
}
|
|
|
|
@Override
|
|
public BlockState rotate(BlockState p_309863_, Rotation p_310613_) {
|
|
return p_309863_.setValue(FACING, p_310613_.rotate(p_309863_.getValue(FACING)));
|
|
}
|
|
|
|
@Override
|
|
public BlockState mirror(BlockState p_311137_, Mirror p_310463_) {
|
|
return p_311137_.rotate(p_310463_.getRotation(p_311137_.getValue(FACING)));
|
|
}
|
|
} |