RyanHub – file viewer
filename: common/src/main/java/rearth/oritech/block/blocks/decorative/TechDoorBlock.java
branch: 1.21
back to repo
package rearth.oritech.block.blocks.decorative;

import com.mojang.serialization.MapCodec;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.sound.SoundCategory;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.Properties;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldView;
import org.jetbrains.annotations.Nullable;
import rearth.oritech.Oritech;
import rearth.oritech.block.entity.decorative.TechDoorBlockEntity;
import rearth.oritech.init.BlockContent;
import rearth.oritech.init.SoundContent;

import java.util.Objects;

public class TechDoorBlock extends HorizontalFacingBlock implements BlockEntityProvider {
    
    public static final BooleanProperty OPENED = BooleanProperty.of("open");
    public static final VoxelShape CLOSED_SHAPE_SOUTH = Block.createCuboidShape(0, 0, 11, 16, 16, 16);
    public static final VoxelShape CLOSED_SHAPE_WEST = Block.createCuboidShape(0, 0, 0, 5, 16, 16);
    public static final VoxelShape CLOSED_SHAPE_NORTH = Block.createCuboidShape(0, 0, 0, 16, 16, 5);
    public static final VoxelShape CLOSED_SHAPE_EAST = Block.createCuboidShape(11, 0, 0, 16, 16, 16);
    
    public TechDoorBlock(Settings settings) {
        super(settings);
        setDefaultState(getDefaultState().with(OPENED, false).with(Properties.HORIZONTAL_FACING, Direction.NORTH));
    }
    
    @Override
    protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
        super.appendProperties(builder);
        builder.add(OPENED);
        builder.add(Properties.HORIZONTAL_FACING);
    }
    
    @Nullable
    @Override
    public BlockState getPlacementState(ItemPlacementContext ctx) {
        return Objects.requireNonNull(super.getPlacementState(ctx)).with(Properties.HORIZONTAL_FACING, ctx.getHorizontalPlayerFacing().getOpposite());
    }
    
    @Override
    public boolean emitsRedstonePower(BlockState state) {
        return true;
    }
    
    @Override
    public void neighborUpdate(BlockState state, World world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
        super.neighborUpdate(state, world, pos, sourceBlock, sourcePos, notify);
        
        if (world.isClient) return;
        
        var isOpen = state.get(OPENED);
        var isPowered = world.isReceivingRedstonePower(pos) || world.isReceivingRedstonePower(pos.up());
        if (isOpen == isPowered) return;

        var aboveState = world.getBlockState(pos.up());
        
        if (!aboveState.getBlock().equals(BlockContent.TECH_DOOR_HINGE)) return;
        
        var entity = (TechDoorBlockEntity) world.getBlockEntity(pos);
        
        if (entity.shouldPlaySoundAgain())
            world.playSound(null, pos, SoundContent.PRESS, SoundCategory.BLOCKS, Oritech.CONFIG.machineVolumeMultiplier() * 0.18f, 1.3f);
        
        world.setBlockState(pos, state.with(OPENED, isPowered));
        world.setBlockState(pos.up(), aboveState.with(OPENED, isPowered));
    }
    
    @Override
    public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
        return getClosedShape(state.get(Properties.HORIZONTAL_FACING));
    }
    
    @Override
    public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
        if (state.get(OPENED))
            return VoxelShapes.empty();
        return super.getCollisionShape(state, world, pos, context);
    }
    
    public static VoxelShape getClosedShape(Direction facing) {
        return switch (facing) {
            case NORTH -> CLOSED_SHAPE_NORTH;
            case EAST -> CLOSED_SHAPE_EAST;
            case SOUTH -> CLOSED_SHAPE_SOUTH;
            case WEST -> CLOSED_SHAPE_WEST;
            default -> VoxelShapes.empty();
        };
    }
    
    @Override
    public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) {
        var belowState = world.getBlockState(pos.down());
        var aboveState = world.getBlockState(pos.up());
        var belowValid = belowState.isSideSolidFullSquare(world, pos.down(), Direction.UP);
        var aboveValid = aboveState.isOf(Blocks.AIR) || aboveState.isIn(TagKey.of(RegistryKeys.BLOCK, Identifier.of("minecraft", "replaceable")));
        return belowValid && aboveValid;
    }
    
    @Override
    public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
        if (!world.isClient)
            world.setBlockState(pos.up(), BlockContent.TECH_DOOR_HINGE.getDefaultState().with(Properties.HORIZONTAL_FACING, state.get(Properties.HORIZONTAL_FACING)));
    }
    
    @Override
    public BlockState onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
        if (!world.isClient)
            world.setBlockState(pos.up(), Blocks.AIR.getDefaultState());
        
        return super.onBreak(world, pos, state, player);
    }
    
    @Override
    protected MapCodec<? extends HorizontalFacingBlock> getCodec() {
        return null;
    }
    
    @Nullable
    @Override
    public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
        return new TechDoorBlockEntity(pos, state);
    }
    
    @Override
    public BlockRenderType getRenderType(BlockState state) {
        return BlockRenderType.ENTITYBLOCK_ANIMATED;
    }
}