ExtraHoppers/src/main/kotlin/net/shadowfacts/extrahoppers/block/grate/GrateBlock.kt

161 lines
5.6 KiB
Kotlin

package net.shadowfacts.extrahoppers.block.grate
import net.fabricmc.fabric.api.block.FabricBlockSettings
import net.minecraft.block.*
import net.minecraft.block.enums.BlockHalf
import net.minecraft.entity.EntityContext
import net.minecraft.entity.EntityType
import net.minecraft.fluid.Fluid
import net.minecraft.fluid.FluidState
import net.minecraft.fluid.Fluids
import net.minecraft.item.ItemPlacementContext
import net.minecraft.sound.BlockSoundGroup
import net.minecraft.state.StateManager
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.world.BlockView
import net.minecraft.world.IWorld
import net.minecraft.world.World
import net.shadowfacts.extrahoppers.block.base.BlockWithEntity
import net.shadowfacts.extrahoppers.util.DynamicFluidStateProvider
/**
* @author shadowfacts
*/
class GrateBlock: BlockWithEntity<GrateBlockEntity>(
FabricBlockSettings.of(Material.METAL, MaterialColor.AIR)
.strength(5f, 6f)
.sounds(BlockSoundGroup.METAL)
.nonOpaque()
.build()
), DynamicFluidStateProvider, FluidFillable, FluidDrainable {
companion object {
val ID = Identifier("extrahoppers", "grate")
val HALF = Properties.BLOCK_HALF
val TOP_SHAPE = createCuboidShape(0.0, 14.0, 0.0, 16.0, 16.0, 16.0)
val BOTTOM_SHAPE = createCuboidShape(0.0, 0.0, 0.0, 16.0, 2.0, 16.0)
}
init {
defaultState = stateManager.defaultState.with(HALF, BlockHalf.BOTTOM)
}
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
builder.add(HALF)
}
override fun getOutlineShape(state: BlockState, world: BlockView, pos: BlockPos, entityContext: EntityContext): VoxelShape {
return when (state.get(HALF)) {
BlockHalf.TOP -> TOP_SHAPE
BlockHalf.BOTTOM -> BOTTOM_SHAPE
}
}
override fun getRayTraceShape(state: BlockState, world: BlockView, pos: BlockPos): VoxelShape {
return when (state.get(HALF)) {
BlockHalf.TOP -> TOP_SHAPE
BlockHalf.BOTTOM -> BOTTOM_SHAPE
}
}
override fun getPlacementState(context: ItemPlacementContext): BlockState {
val half = when (context.side) {
Direction.DOWN -> BlockHalf.TOP
Direction.UP -> BlockHalf.BOTTOM
else -> if (context.hitPos.y - context.blockPos.y > 0.5) BlockHalf.TOP else BlockHalf.BOTTOM
}
return defaultState.with(HALF, half)
}
override fun createBlockEntity(world: BlockView) = GrateBlockEntity()
override fun isTranslucent(state: BlockState, world: BlockView, pos: BlockPos): Boolean {
return true
}
override fun isSimpleFullBlock(state: BlockState, world: BlockView, pos: BlockPos): Boolean {
return false
}
override fun allowsSpawning(state: BlockState, world: BlockView, pos: BlockPos, entityType: EntityType<*>): Boolean {
return false
}
override fun getFluidState(state: BlockState, world: BlockView, pos: BlockPos): FluidState {
return getBlockEntity(world, pos)?.fluidState ?: Fluids.EMPTY.defaultState
}
override fun setEmptyFluid(world: World, pos: BlockPos) {
val be = getBlockEntity(world, pos) ?: return
be.fluidState = null
if (!world.isClient) {
be.sync()
}
triggerFluidUpdate(world, pos, world.getBlockState(pos))
}
override fun allowsFlow(toSide: Direction, state: BlockState, world: BlockView, pos: BlockPos): DynamicFluidStateProvider.FlowResult {
return DynamicFluidStateProvider.FlowResult.ALLOW
}
override fun neighborUpdate(state: BlockState, world: World, pos: BlockPos, block: Block, neighborPos: BlockPos, bl: Boolean) {
val fluidState = getFluidState(state, world, pos)
if (!fluidState.isEmpty) {
world.fluidTickScheduler.schedule(pos, fluidState.fluid, fluidState.fluid.getTickRate(world))
}
}
private fun triggerFluidUpdate(world: World, pos: BlockPos, state: BlockState) {
world.updateListeners(pos, state, state, 3)
world.updateNeighbors(pos, state.block)
}
// Fluid Fillable
override fun canFillWithFluid(world: BlockView, pos: BlockPos, state: BlockState, fluid: Fluid): Boolean {
val be = getBlockEntity(world, pos)
return be != null && be.fluidState == null
}
override fun tryFillWithFluid(world: IWorld, pos: BlockPos, state: BlockState, fluidState: FluidState): Boolean {
val be = getBlockEntity(world, pos)
return if (be != null) {
be.fluidState = fluidState
if (!world.isClient) {
world.fluidTickScheduler.schedule(pos, fluidState.fluid, fluidState.fluid.getTickRate(world))
be.sync()
}
if (world is World) {
triggerFluidUpdate(world, pos, state)
}
true
} else {
false
}
}
override fun tryDrainFluid(world: IWorld, pos: BlockPos, state: BlockState): Fluid {
val be = getBlockEntity(world, pos) ?: return Fluids.EMPTY
val fluidState = be.fluidState ?: return Fluids.EMPTY
return if (fluidState.isStill) {
be.fluidState = null
if (!world.isClient) {
be.sync()
}
if (world is World) {
triggerFluidUpdate(world, pos, state)
}
fluidState.fluid
} else {
Fluids.EMPTY
}
}
}