package net.shadowfacts.phycon.network.block.cable import net.fabricmc.api.EnvType import net.fabricmc.api.Environment import net.minecraft.block.* import net.minecraft.block.piston.PistonBehavior import net.minecraft.entity.EntityContext import net.minecraft.item.ItemPlacementContext import net.minecraft.state.StateFactory import net.minecraft.state.property.BooleanProperty 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.IWorld import net.minecraft.world.World import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.api.NetworkCable import net.shadowfacts.phycon.api.NetworkComponent import java.util.* /** * @author shadowfacts */ class CableBlock: Block(Settings.of(CABLE_MATERIAL)), NetworkCable { companion object { val ID = Identifier(PhysicalConnectivity.MODID, "cable") val CABLE_MATERIAL = Material(MaterialColor.IRON, false, false, true, false, true, false, false, PistonBehavior.NORMAL) val CENTER_SHAPE = createCuboidShape(6.0, 6.0, 6.0, 10.0, 10.0, 10.0) val SIDE_SHAPES = mapOf( Direction.DOWN to createCuboidShape(6.0, 0.0, 6.0, 10.0, 6.0, 10.0), Direction.UP to createCuboidShape(6.0, 10.0, 6.0, 10.0, 16.0, 10.0), Direction.NORTH to createCuboidShape(6.0, 6.0, 0.0, 10.0, 10.0, 6.0), Direction.SOUTH to createCuboidShape(6.0, 6.0, 10.0, 10.0, 10.0, 16.0), Direction.WEST to createCuboidShape(0.0, 6.0, 6.0, 6.0, 10.0, 10.0), Direction.EAST to createCuboidShape(10.0, 6.0, 6.0, 16.0, 10.0, 10.0) ) private val SHAPE_CACHE = mutableMapOf() val CONNECTIONS: Map = Direction.values().associate { it to BooleanProperty.of(it.name.toLowerCase()) } fun getShape(state: BlockState): VoxelShape { return SHAPE_CACHE.getOrPut(state) { var shape = CENTER_SHAPE for ((side, prop) in CONNECTIONS) { if (state[prop]) { shape = VoxelShapes.union(shape, SIDE_SHAPES[side]) } } return shape } } } init { defaultState = CONNECTIONS.values.fold(stateFactory.defaultState) { acc, prop -> acc.with(prop, false) } } override fun getNetworkConnectedSides(state: BlockState, world: World, pos: BlockPos): Set { val set = EnumSet.noneOf(Direction::class.java) for ((side, prop) in CONNECTIONS) { if (state[prop]) { set.add(side) } } return set } override fun appendProperties(builder: StateFactory.Builder) { super.appendProperties(builder) CONNECTIONS.values.forEach { builder.add(it) } } override fun getPlacementState(context: ItemPlacementContext): BlockState { return CONNECTIONS.entries.fold(defaultState, { acc, (dir, prop) -> acc.with(prop, hasConnectionInDirection(context.world, context.blockPos, dir)) }) } override fun getStateForNeighborUpdate(state: BlockState, side: Direction, neighborState: BlockState, world: IWorld, blockPos_1: BlockPos, blockPos_2: BlockPos): BlockState { return state.with(CONNECTIONS[side], hasConnectionInDirection(world, blockPos_1, side)) } private fun hasConnectionInDirection(world: IWorld, pos: BlockPos, direction: Direction): Boolean { val block = world.getBlockState(pos.offset(direction)).block return block is NetworkComponent } @Environment(EnvType.CLIENT) override fun getRenderLayer(): BlockRenderLayer { return BlockRenderLayer.TRANSLUCENT } override fun isOpaque(blockState_1: BlockState?): Boolean { return false } override fun isTranslucent(blockState_1: BlockState?, blockView_1: BlockView?, blockPos_1: BlockPos?): Boolean { return true } override fun isSimpleFullBlock(blockState_1: BlockState?, blockView_1: BlockView?, blockPos_1: BlockPos?): Boolean { return false } override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: EntityContext): VoxelShape { return getShape(state) } }