PhysicalConnectivity/src/main/kotlin/net/shadowfacts/phycon/block/inserter/InserterBlock.kt

149 lines
4.9 KiB
Kotlin

package net.shadowfacts.phycon.block.inserter
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.block.Material
import net.minecraft.block.ShapeContext
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.entity.player.PlayerInventory
import net.minecraft.item.ItemPlacementContext
import net.minecraft.item.ItemStack
import net.minecraft.network.PacketByteBuf
import net.minecraft.screen.ScreenHandler
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.sound.BlockSoundGroup
import net.minecraft.state.StateManager
import net.minecraft.state.property.Properties
import net.minecraft.text.Text
import net.minecraft.util.ActionResult
import net.minecraft.util.Hand
import net.minecraft.util.Identifier
import net.minecraft.util.hit.BlockHitResult
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.WorldAccess
import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.api.Interface
import net.shadowfacts.phycon.block.DeviceBlock
import net.shadowfacts.phycon.block.extractor.ExtractorBlock
import java.util.*
/**
* @author shadowfacts
*/
class InserterBlock: DeviceBlock<InserterBlockEntity>(
Settings.of(Material.METAL)
.strength(1.5f)
.sounds(BlockSoundGroup.METAL)
) {
companion object {
val ID = Identifier(PhysicalConnectivity.MODID, "inserter")
val FACING = Properties.FACING
private val INSERTER_SHAPES = mutableMapOf<Direction, VoxelShape>()
init {
val components = arrayOf(
doubleArrayOf(4.0, 0.0, 4.0, 12.0, 2.0, 12.0),
doubleArrayOf(2.0, 2.0, 2.0, 14.0, 4.0, 14.0),
doubleArrayOf(0.0, 4.0, 0.0, 16.0, 6.0, 16.0),
doubleArrayOf(6.0, 6.0, 6.0, 10.0, 16.0, 10.0)
)
val directions = arrayOf(
Triple(Direction.DOWN, null, false),
Triple(Direction.UP, null, true),
Triple(Direction.NORTH, 2, false),
Triple(Direction.SOUTH, 2, true),
Triple(Direction.WEST, 1, false),
Triple(Direction.EAST, 1, true),
)
for ((dir, rotate, flip) in directions) {
val shapes = components.map { it ->
val arr = it.copyOf()
if (rotate != null) {
for (i in 0 until 3) {
arr[i] = it[(i + rotate) % 3]
arr[3 + i] = it[3 + ((i + rotate) % 3)]
}
}
if (flip) {
for (i in arr.indices) {
arr[i] = 16.0 - arr[i]
}
}
createCuboidShape(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5])
}
INSERTER_SHAPES[dir] = shapes.reduce { a, b -> VoxelShapes.union(a, b) }
}
}
}
override fun getNetworkConnectedSides(state: BlockState, world: WorldAccess, pos: BlockPos): Collection<Direction> {
return EnumSet.of(state[FACING].opposite)
}
override fun getNetworkInterfaceForSide(side: Direction, state: BlockState, world: WorldAccess, pos: BlockPos): Interface? {
return if (side == state[FACING].opposite) {
getBlockEntity(world, pos)
} else {
null
}
}
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
super.appendProperties(builder)
builder.add(FACING)
}
override fun createBlockEntity(world: BlockView) = InserterBlockEntity()
override fun getPlacementState(context: ItemPlacementContext): BlockState {
val facing = if (context.player?.isSneaking == true) context.side.opposite else context.playerLookDirection.opposite
return defaultState.with(FACING, facing)
}
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
return INSERTER_SHAPES[state[FACING]]!!
}
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) {
if (!world.isClient) {
getBlockEntity(world, pos)!!.updateInventory()
}
}
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, bl: Boolean) {
if (!world.isClient) {
getBlockEntity(world, pos)!!.updateInventory()
}
}
override fun onUse(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hitResult: BlockHitResult): ActionResult {
if (!world.isClient) {
val be = getBlockEntity(world, pos)!!
be.sync()
val factory = object: ExtendedScreenHandlerFactory {
override fun createMenu(syncId: Int, playerInv: PlayerInventory, player: PlayerEntity): ScreenHandler {
return InserterScreenHandler(syncId, playerInv, be)
}
override fun getDisplayName() = this@InserterBlock.name
override fun writeScreenOpeningData(player: ServerPlayerEntity, buf: PacketByteBuf) {
buf.writeBlockPos(be.pos)
}
}
player.openHandledScreen(factory)
}
return ActionResult.SUCCESS
}
}