181 lines
7.2 KiB
Java
181 lines
7.2 KiB
Java
package net.minecraft.world.level.block;
|
|
|
|
import com.mojang.serialization.MapCodec;
|
|
import java.util.Arrays;
|
|
import java.util.UUID;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.network.chat.CommonComponents;
|
|
import net.minecraft.network.chat.contents.PlainTextContents;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.stats.Stats;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.ItemInteractionResult;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.SignApplicator;
|
|
import net.minecraft.world.level.BlockGetter;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.LevelAccessor;
|
|
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.entity.SignBlockEntity;
|
|
import net.minecraft.world.level.block.entity.SignText;
|
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
|
import net.minecraft.world.level.block.state.properties.WoodType;
|
|
import net.minecraft.world.level.gameevent.GameEvent;
|
|
import net.minecraft.world.level.material.FluidState;
|
|
import net.minecraft.world.level.material.Fluids;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraft.world.phys.shapes.CollisionContext;
|
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterloggedBlock {
|
|
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
|
|
protected static final float AABB_OFFSET = 4.0F;
|
|
protected static final VoxelShape SHAPE = Block.box(4.0, 0.0, 4.0, 12.0, 16.0, 12.0);
|
|
private final WoodType type;
|
|
|
|
protected SignBlock(WoodType type, BlockBehaviour.Properties properties) {
|
|
super(properties);
|
|
this.type = type;
|
|
}
|
|
|
|
@Override
|
|
protected abstract MapCodec<? extends SignBlock> codec();
|
|
|
|
@Override
|
|
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
|
|
if ((Boolean)state.getValue(WATERLOGGED)) {
|
|
level.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
|
|
}
|
|
|
|
return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
|
|
}
|
|
|
|
@Override
|
|
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
|
|
return SHAPE;
|
|
}
|
|
|
|
@Override
|
|
public boolean isPossibleToRespawnInThis(BlockState state) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
|
return new SignBlockEntity(pos, state);
|
|
}
|
|
|
|
@Override
|
|
protected ItemInteractionResult useItemOn(
|
|
ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hitResult
|
|
) {
|
|
if (level.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity) {
|
|
SignApplicator signApplicator2 = stack.getItem() instanceof SignApplicator signApplicator ? signApplicator : null;
|
|
boolean bl = signApplicator2 != null && player.mayBuild();
|
|
if (!level.isClientSide) {
|
|
if (bl && !signBlockEntity.isWaxed() && !this.otherPlayerIsEditingSign(player, signBlockEntity)) {
|
|
boolean bl2 = signBlockEntity.isFacingFrontText(player);
|
|
if (signApplicator2.canApplyToSign(signBlockEntity.getText(bl2), player) && signApplicator2.tryApplyToSign(level, signBlockEntity, bl2, player)) {
|
|
signBlockEntity.executeClickCommandsIfPresent(player, level, pos, bl2);
|
|
player.awardStat(Stats.ITEM_USED.get(stack.getItem()));
|
|
level.gameEvent(GameEvent.BLOCK_CHANGE, signBlockEntity.getBlockPos(), GameEvent.Context.of(player, signBlockEntity.getBlockState()));
|
|
stack.consume(1, player);
|
|
return ItemInteractionResult.SUCCESS;
|
|
} else {
|
|
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
|
|
}
|
|
} else {
|
|
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
|
|
}
|
|
} else {
|
|
return !bl && !signBlockEntity.isWaxed() ? ItemInteractionResult.CONSUME : ItemInteractionResult.SUCCESS;
|
|
}
|
|
} else {
|
|
return ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
|
|
if (level.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity) {
|
|
if (level.isClientSide) {
|
|
Util.pauseInIde(new IllegalStateException("Expected to only call this on server"));
|
|
}
|
|
|
|
boolean bl = signBlockEntity.isFacingFrontText(player);
|
|
boolean bl2 = signBlockEntity.executeClickCommandsIfPresent(player, level, pos, bl);
|
|
if (signBlockEntity.isWaxed()) {
|
|
level.playSound(null, signBlockEntity.getBlockPos(), signBlockEntity.getSignInteractionFailedSoundEvent(), SoundSource.BLOCKS);
|
|
return InteractionResult.SUCCESS;
|
|
} else if (bl2) {
|
|
return InteractionResult.SUCCESS;
|
|
} else if (!this.otherPlayerIsEditingSign(player, signBlockEntity) && player.mayBuild() && this.hasEditableText(player, signBlockEntity, bl)) {
|
|
this.openTextEdit(player, signBlockEntity, bl);
|
|
return InteractionResult.SUCCESS;
|
|
} else {
|
|
return InteractionResult.PASS;
|
|
}
|
|
} else {
|
|
return InteractionResult.PASS;
|
|
}
|
|
}
|
|
|
|
private boolean hasEditableText(Player player, SignBlockEntity signEntity, boolean isFrontText) {
|
|
SignText signText = signEntity.getText(isFrontText);
|
|
return Arrays.stream(signText.getMessages(player.isTextFilteringEnabled()))
|
|
.allMatch(component -> component.equals(CommonComponents.EMPTY) || component.getContents() instanceof PlainTextContents);
|
|
}
|
|
|
|
public abstract float getYRotationDegrees(BlockState state);
|
|
|
|
public Vec3 getSignHitboxCenterPosition(BlockState state) {
|
|
return new Vec3(0.5, 0.5, 0.5);
|
|
}
|
|
|
|
@Override
|
|
protected FluidState getFluidState(BlockState state) {
|
|
return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
|
|
}
|
|
|
|
public WoodType type() {
|
|
return this.type;
|
|
}
|
|
|
|
public static WoodType getWoodType(Block block) {
|
|
WoodType woodType;
|
|
if (block instanceof SignBlock) {
|
|
woodType = ((SignBlock)block).type();
|
|
} else {
|
|
woodType = WoodType.OAK;
|
|
}
|
|
|
|
return woodType;
|
|
}
|
|
|
|
public void openTextEdit(Player player, SignBlockEntity signEntity, boolean isFrontText) {
|
|
signEntity.setAllowedPlayerEditor(player.getUUID());
|
|
player.openTextEdit(signEntity, isFrontText);
|
|
}
|
|
|
|
private boolean otherPlayerIsEditingSign(Player player, SignBlockEntity signEntity) {
|
|
UUID uUID = signEntity.getPlayerWhoMayEdit();
|
|
return uUID != null && !uUID.equals(player.getUUID());
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
|
|
return createTickerHelper(blockEntityType, BlockEntityType.SIGN, SignBlockEntity::tick);
|
|
}
|
|
}
|