Basic Grate implementation
This commit is contained in:
parent
5e42cbddce
commit
22891a9692
|
@ -0,0 +1,58 @@
|
|||
package net.shadowfacts.extrahoppers.mixin;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.fluid.BaseFluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.world.WorldView;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import net.shadowfacts.extrahoppers.util.FluidFlowControllable;
|
||||
import net.shadowfacts.extrahoppers.util.PositionedFluidStateProvider;
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
@Mixin(BaseFluid.class)
|
||||
public abstract class MixinBaseFluid {
|
||||
|
||||
@ModifyVariable(
|
||||
method = "getUpdatedState(Lnet/minecraft/world/WorldView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)Lnet/minecraft/fluid/FluidState;",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/fluid/FluidState;isEmpty()Z", shift = At.Shift.BEFORE),
|
||||
index = 8,
|
||||
ordinal = 0,
|
||||
require = 1
|
||||
)
|
||||
private FluidState getUpdatedState(FluidState initial, WorldView world, BlockPos pos, BlockState state) {
|
||||
BlockPos up = pos.up();
|
||||
BlockState upState = world.getBlockState(up);
|
||||
if (upState.getBlock() instanceof PositionedFluidStateProvider) {
|
||||
return ((PositionedFluidStateProvider)upState.getBlock()).getFluidState(upState, world, up);
|
||||
}
|
||||
return initial;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "receivesFlow(Lnet/minecraft/util/math/Direction;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)Z",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void receivesFlow(Direction direction, BlockView world, BlockPos pos, BlockState state, BlockPos fromPos, BlockState fromState, CallbackInfoReturnable<Boolean> cir) {
|
||||
FluidFlowControllable.Result result = FluidFlowControllable.Result.DEFAULT;
|
||||
if (state.getBlock() instanceof FluidFlowControllable) {
|
||||
result = ((FluidFlowControllable)state.getBlock()).allowsFlow(direction, state, world, pos);
|
||||
}
|
||||
if (result != FluidFlowControllable.Result.DENY && fromState.getBlock() instanceof FluidFlowControllable) {
|
||||
result = ((FluidFlowControllable)fromState.getBlock()).allowsFlow(direction, fromState, world, fromPos);
|
||||
}
|
||||
if (result != FluidFlowControllable.Result.DEFAULT) {
|
||||
cir.setReturnValue(result == FluidFlowControllable.Result.ALLOW);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package net.shadowfacts.extrahoppers.mixin;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.WorldChunk;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import net.shadowfacts.extrahoppers.util.PositionedFluidStateProvider;
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
@Mixin(WorldChunk.class)
|
||||
public abstract class MixinWorldChunk implements Chunk {
|
||||
|
||||
@Shadow
|
||||
private World world;
|
||||
|
||||
@Inject(method = "getFluidState(III)Lnet/minecraft/fluid/FluidState;", at = @At("HEAD"), cancellable = true)
|
||||
public void getFluidState(int x, int y, int z, CallbackInfoReturnable<FluidState> cir) {
|
||||
BlockPos pos = new BlockPos(x, y, z);
|
||||
BlockState state = getBlockState(pos);
|
||||
if (state.getBlock() instanceof PositionedFluidStateProvider) {
|
||||
FluidState fluidState = ((PositionedFluidStateProvider)state.getBlock()).getFluidState(state, world, pos);
|
||||
cir.setReturnValue(fluidState);
|
||||
cir.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package net.shadowfacts.extrahoppers.util;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
public interface FluidFlowControllable {
|
||||
|
||||
@NotNull
|
||||
Result allowsFlow(@NotNull Direction toSide, @NotNull BlockState state, @NotNull BlockView world, @NotNull BlockPos pos);
|
||||
|
||||
enum Result {
|
||||
ALLOW,
|
||||
DENY,
|
||||
DEFAULT
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package net.shadowfacts.extrahoppers.util;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.BlockView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
public interface PositionedFluidStateProvider {
|
||||
FluidState getFluidState(@NotNull BlockState state, @NotNull BlockView world, @NotNull BlockPos pos);
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
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.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.shadowfacts.extrahoppers.block.base.BlockWithEntity
|
||||
import net.shadowfacts.extrahoppers.util.FluidFlowControllable
|
||||
import net.shadowfacts.extrahoppers.util.PositionedFluidStateProvider
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class GrateBlock: BlockWithEntity<GrateBlockEntity>(
|
||||
FabricBlockSettings.of(Material.METAL, MaterialColor.AIR)
|
||||
.strength(5f, 6f)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
.nonOpaque()
|
||||
.build()
|
||||
), PositionedFluidStateProvider, FluidFlowControllable, FluidFillable, FluidDrainable {
|
||||
|
||||
companion object {
|
||||
val ID = Identifier("extrahoppers", "grate")
|
||||
|
||||
val HALF = Properties.BLOCK_HALF
|
||||
|
||||
val TOP_SHAPE = createCuboidShape(0.0, 15.0, 0.0, 16.0, 16.0, 16.0)
|
||||
val BOTTOM_SHAPE = createCuboidShape(0.0, 0.0, 0.0, 16.0, 1.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 getFluidState(state: BlockState, world: BlockView, pos: BlockPos): FluidState {
|
||||
return getBlockEntity(world, pos)?.fluidState ?: Fluids.EMPTY.defaultState
|
||||
}
|
||||
|
||||
override fun allowsFlow(toSide: Direction, state: BlockState, world: BlockView, pos: BlockPos): FluidFlowControllable.Result {
|
||||
return FluidFlowControllable.Result.ALLOW
|
||||
}
|
||||
|
||||
|
||||
// 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) {
|
||||
if (!world.isClient) {
|
||||
be.fluidState = fluidState
|
||||
world.fluidTickScheduler.schedule(pos, fluidState.fluid, fluidState.fluid.getTickRate(world))
|
||||
be.sync()
|
||||
}
|
||||
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) {
|
||||
if (!world.isClient) {
|
||||
be.fluidState = null
|
||||
be.sync()
|
||||
}
|
||||
fluidState.fluid
|
||||
} else {
|
||||
Fluids.EMPTY
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package net.shadowfacts.extrahoppers.block.grate
|
||||
|
||||
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
|
||||
import net.fabricmc.fabric.api.util.NbtType
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.fluid.FluidState
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.NbtHelper
|
||||
import net.shadowfacts.extrahoppers.init.EHBlockEntities
|
||||
|
||||
/**
|
||||
* @author shadowfacts
|
||||
*/
|
||||
class GrateBlockEntity: BlockEntity(EHBlockEntities.GRATE), BlockEntityClientSerializable {
|
||||
|
||||
var fluidState: FluidState? = null
|
||||
|
||||
override fun toTag(tag: CompoundTag): CompoundTag {
|
||||
fluidState?.also {
|
||||
tag.put("fluid", NbtHelper.fromBlockState(it.blockState))
|
||||
}
|
||||
return super.toTag(tag)
|
||||
}
|
||||
|
||||
override fun fromTag(tag: CompoundTag) {
|
||||
super.fromTag(tag)
|
||||
if (tag.contains("fluid", NbtType.COMPOUND)) {
|
||||
fluidState = NbtHelper.toBlockState(tag.getCompound("fluid")).fluidState
|
||||
}
|
||||
}
|
||||
|
||||
override fun toClientTag(tag: CompoundTag): CompoundTag {
|
||||
fluidState?.also {
|
||||
tag.put("fluid", NbtHelper.fromBlockState(it.blockState))
|
||||
}
|
||||
return tag
|
||||
}
|
||||
|
||||
override fun fromClientTag(tag: CompoundTag) {
|
||||
if (tag.contains("fluid", NbtType.COMPOUND)) {
|
||||
fluidState = NbtHelper.toBlockState(tag.getCompound("fluid")).fluidState
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -8,6 +8,8 @@ import net.minecraft.util.registry.Registry
|
|||
import net.shadowfacts.extrahoppers.block.gold.GoldHopperBlock
|
||||
import net.shadowfacts.extrahoppers.block.gold.GoldHopperBlockEntity
|
||||
import net.shadowfacts.extrahoppers.block.gold.InvertedGoldHopperBlock
|
||||
import net.shadowfacts.extrahoppers.block.grate.GrateBlock
|
||||
import net.shadowfacts.extrahoppers.block.grate.GrateBlockEntity
|
||||
import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlock
|
||||
import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlockEntity
|
||||
|
||||
|
@ -16,12 +18,13 @@ object EHBlockEntities {
|
|||
val WOOD_HOPPER = create(::WoodHopperBlockEntity, EHBlocks.WOOD_HOPPER)
|
||||
val GOLD_HOPPER = create({ GoldHopperBlockEntity(false) }, EHBlocks.GOLD_HOPPER)
|
||||
val INVERTED_GOLD_HOPPER = create({ GoldHopperBlockEntity(true) }, EHBlocks.INVERTED_GOLD_HOPPER)
|
||||
// val INVERTED_GOLD_HOPPER = create(::InvertedGoldHopperBlockEntity, EHBlocks.INVERTED_GOLD_HOPPER)
|
||||
val GRATE = create(::GrateBlockEntity, EHBlocks.GRATE)
|
||||
|
||||
fun init() {
|
||||
register(WoodHopperBlock.ID, WOOD_HOPPER)
|
||||
register(GoldHopperBlock.ID, GOLD_HOPPER)
|
||||
register(InvertedGoldHopperBlock.ID, INVERTED_GOLD_HOPPER)
|
||||
register(GrateBlock.ID, GRATE)
|
||||
}
|
||||
|
||||
private fun <T: BlockEntity> create(builder: () -> T, block: Block): BlockEntityType<T> {
|
||||
|
|
|
@ -5,6 +5,7 @@ import net.minecraft.util.Identifier
|
|||
import net.minecraft.util.registry.Registry
|
||||
import net.shadowfacts.extrahoppers.block.gold.GoldHopperBlock
|
||||
import net.shadowfacts.extrahoppers.block.gold.InvertedGoldHopperBlock
|
||||
import net.shadowfacts.extrahoppers.block.grate.GrateBlock
|
||||
import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlock
|
||||
|
||||
object EHBlocks {
|
||||
|
@ -12,11 +13,13 @@ object EHBlocks {
|
|||
val WOOD_HOPPER = WoodHopperBlock()
|
||||
val GOLD_HOPPER = GoldHopperBlock()
|
||||
val INVERTED_GOLD_HOPPER = InvertedGoldHopperBlock()
|
||||
val GRATE = GrateBlock()
|
||||
|
||||
fun init() {
|
||||
register(WoodHopperBlock.ID, WOOD_HOPPER)
|
||||
register(GoldHopperBlock.ID, GOLD_HOPPER)
|
||||
register(InvertedGoldHopperBlock.ID, INVERTED_GOLD_HOPPER)
|
||||
register(GrateBlock.ID, GRATE)
|
||||
}
|
||||
|
||||
private fun register(id: Identifier, block: Block) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import net.minecraft.util.Identifier
|
|||
import net.minecraft.util.registry.Registry
|
||||
import net.shadowfacts.extrahoppers.block.gold.GoldHopperBlock
|
||||
import net.shadowfacts.extrahoppers.block.gold.InvertedGoldHopperBlock
|
||||
import net.shadowfacts.extrahoppers.block.grate.GrateBlock
|
||||
import net.shadowfacts.extrahoppers.block.wood.WoodHopperBlock
|
||||
|
||||
object EHItems {
|
||||
|
@ -13,11 +14,13 @@ object EHItems {
|
|||
val WOOD_HOPPER = BlockItem(EHBlocks.WOOD_HOPPER, Item.Settings())
|
||||
val GOLD_HOPPER = BlockItem(EHBlocks.GOLD_HOPPER, Item.Settings())
|
||||
val INVERTED_GOLD_HOPPER = BlockItem(EHBlocks.INVERTED_GOLD_HOPPER, Item.Settings())
|
||||
val GRATE = BlockItem(EHBlocks.GRATE, Item.Settings())
|
||||
|
||||
fun init() {
|
||||
register(WoodHopperBlock.ID, WOOD_HOPPER)
|
||||
register(GoldHopperBlock.ID, GOLD_HOPPER)
|
||||
register(InvertedGoldHopperBlock.ID, INVERTED_GOLD_HOPPER)
|
||||
register(GrateBlock.ID, GRATE)
|
||||
}
|
||||
|
||||
private fun register(id: Identifier, item: Item) {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"variants": {
|
||||
"half=top": { "model": "extrahoppers:block/grate" },
|
||||
"half=bottom": { "model": "extrahoppers:block/grate", "x": 180 }
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"block.extrahoppers.wood_hopper": "Wooden Hopper",
|
||||
"block.extrahoppers.gold_hopper": "Golden Hopper",
|
||||
"block.extrahoppers.inverted_gold_hopper": "Inverted Golden Hopper"
|
||||
"block.extrahoppers.inverted_gold_hopper": "Inverted Golden Hopper",
|
||||
"block.extrahoppers.grate": "Grate"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"ambientocclusion": false,
|
||||
"textures": {
|
||||
"face": "extrahoppers:block/grate/face",
|
||||
"edge": "extrahoppers:block/grate/edge"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [0, 15, 0],
|
||||
"to": [16, 16, 16],
|
||||
"faces": {
|
||||
"down": {"texture": "#face"},
|
||||
"up": {"texture": "#face", "cullface": "up"},
|
||||
"north": {"texture": "#edge", "cullface": "north"},
|
||||
"south": {"texture": "#edge", "cullface": "south"},
|
||||
"west": {"texture": "#edge", "cullface": "west"},
|
||||
"east": {"texture": "#edge", "cullface": "east"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"gui": {
|
||||
"rotation": [ 30, 225, 0 ],
|
||||
"translation": [ 0, 0, 0],
|
||||
"scale":[ 0.625, 0.625, 0.625 ]
|
||||
},
|
||||
"ground": {
|
||||
"rotation": [ 0, 0, 0 ],
|
||||
"translation": [ 0, 3, 0],
|
||||
"scale":[ 0.25, 0.25, 0.25 ]
|
||||
},
|
||||
"fixed": {
|
||||
"rotation": [ 0, 0, 0 ],
|
||||
"translation": [ 0, 0, 0],
|
||||
"scale":[ 0.5, 0.5, 0.5 ]
|
||||
},
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [ 75, 45, 0 ],
|
||||
"translation": [ 0, 2.5, 0],
|
||||
"scale": [ 0.375, 0.375, 0.375 ]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [ 0, 45, 0 ],
|
||||
"translation": [ 0, 0, 0 ],
|
||||
"scale": [ 0.40, 0.40, 0.40 ]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [ 0, 225, 0 ],
|
||||
"translation": [ 0, 0, 0 ],
|
||||
"scale": [ 0.40, 0.40, 0.40 ]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "extrahoppers:block/grate"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "net.shadowfacts.extrahoppers.mixin",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"MixinWorldChunk",
|
||||
"MixinBaseFluid"
|
||||
],
|
||||
"client": [
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
|
@ -17,6 +17,9 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
"extrahoppers.mixins.json"
|
||||
],
|
||||
"depends": {
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue