From dd92515c2f6c238510c830f2b68299d31b81df48 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 29 Mar 2020 12:17:29 -0400 Subject: [PATCH] Grate fluid interaction improvements --- .../extrahoppers/mixin/MixinBaseFluid.java | 42 ++++++++++++++----- .../extrahoppers/mixin/MixinBucketItem.java | 37 ++++++++++++++++ .../extrahoppers/mixin/MixinWorldChunk.java | 6 +-- .../util/DynamicFluidStateProvider.java | 27 ++++++++++++ .../util/FluidFlowControllable.java | 23 ---------- .../util/PositionedFluidStateProvider.java | 14 ------- .../extrahoppers/block/grate/GrateBlock.kt | 40 ++++++++++++++---- .../block/grate/GrateBlockEntity.kt | 13 ++++-- src/main/resources/extrahoppers.mixins.json | 5 ++- 9 files changed, 143 insertions(+), 64 deletions(-) create mode 100644 src/main/java/net/shadowfacts/extrahoppers/mixin/MixinBucketItem.java create mode 100644 src/main/java/net/shadowfacts/extrahoppers/util/DynamicFluidStateProvider.java delete mode 100644 src/main/java/net/shadowfacts/extrahoppers/util/FluidFlowControllable.java delete mode 100644 src/main/java/net/shadowfacts/extrahoppers/util/PositionedFluidStateProvider.java diff --git a/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinBaseFluid.java b/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinBaseFluid.java index 5489b9b..dd244e4 100644 --- a/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinBaseFluid.java +++ b/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinBaseFluid.java @@ -6,14 +6,17 @@ 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.IWorld; +import net.minecraft.world.World; import net.minecraft.world.WorldView; 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.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import net.shadowfacts.extrahoppers.util.FluidFlowControllable; -import net.shadowfacts.extrahoppers.util.PositionedFluidStateProvider; +import net.shadowfacts.extrahoppers.util.DynamicFluidStateProvider; /** * @author shadowfacts @@ -31,8 +34,8 @@ public abstract class MixinBaseFluid { 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); + if (upState.getBlock() instanceof DynamicFluidStateProvider) { + return ((DynamicFluidStateProvider)upState.getBlock()).getFluidState(upState, world, up); } return initial; } @@ -43,16 +46,33 @@ public abstract class MixinBaseFluid { cancellable = true ) private void receivesFlow(Direction direction, BlockView world, BlockPos pos, BlockState state, BlockPos fromPos, BlockState fromState, CallbackInfoReturnable cir) { - FluidFlowControllable.Result result = FluidFlowControllable.Result.DEFAULT; - if (state.getBlock() instanceof FluidFlowControllable) { - result = ((FluidFlowControllable)state.getBlock()).allowsFlow(direction, state, world, pos); + DynamicFluidStateProvider.FlowResult result = DynamicFluidStateProvider.FlowResult.DEFAULT; + if (state.getBlock() instanceof DynamicFluidStateProvider) { + result = ((DynamicFluidStateProvider)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 != DynamicFluidStateProvider.FlowResult.DENY && fromState.getBlock() instanceof DynamicFluidStateProvider) { + result = ((DynamicFluidStateProvider)fromState.getBlock()).allowsFlow(direction, fromState, world, fromPos); } - if (result != FluidFlowControllable.Result.DEFAULT) { - cir.setReturnValue(result == FluidFlowControllable.Result.ALLOW); + if (result != DynamicFluidStateProvider.FlowResult.DEFAULT) { + cir.setReturnValue(result == DynamicFluidStateProvider.FlowResult.ALLOW); } } + @Inject( + method = "onScheduledTick(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/fluid/FluidState;)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z"), + cancellable = true + ) + private void onScheduledTick(World world, BlockPos pos, FluidState fluidState, CallbackInfo ci) { + BlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof DynamicFluidStateProvider) { + ((DynamicFluidStateProvider)state.getBlock()).setEmptyFluid(world, pos); + this.tryFlow(world, pos, fluidState); + ci.cancel(); + } + } + + @Shadow + protected abstract void tryFlow(IWorld world, BlockPos pos, FluidState state); + } diff --git a/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinBucketItem.java b/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinBucketItem.java new file mode 100644 index 0000000..1a97804 --- /dev/null +++ b/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinBucketItem.java @@ -0,0 +1,37 @@ +package net.shadowfacts.extrahoppers.mixin; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.Fluids; +import net.minecraft.item.BucketItem; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.shadowfacts.extrahoppers.util.DynamicFluidStateProvider; +import org.objectweb.asm.Opcodes; +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.Redirect; + +/** + * @author shadowfacts + */ +@Mixin(BucketItem.class) +public abstract class MixinBucketItem { + + @Shadow + private Fluid fluid; + + @Redirect( + method = "placeFluid(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/hit/BlockHitResult;)Z", + at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/item/BucketItem;fluid:Lnet/minecraft/fluid/Fluid;", ordinal = 4) + ) + private Fluid getFluid(BucketItem item, PlayerEntity player, World world, BlockPos pos, BlockHitResult result) { + if (world.getBlockState(pos).getBlock() instanceof DynamicFluidStateProvider) { + return Fluids.WATER; + } else { + return this.fluid; + } + } +} diff --git a/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinWorldChunk.java b/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinWorldChunk.java index 7f9c007..5a6fa35 100644 --- a/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinWorldChunk.java +++ b/src/main/java/net/shadowfacts/extrahoppers/mixin/MixinWorldChunk.java @@ -11,7 +11,7 @@ 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; +import net.shadowfacts.extrahoppers.util.DynamicFluidStateProvider; /** * @author shadowfacts @@ -26,8 +26,8 @@ public abstract class MixinWorldChunk implements Chunk { public void getFluidState(int x, int y, int z, CallbackInfoReturnable 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); + if (state.getBlock() instanceof DynamicFluidStateProvider) { + FluidState fluidState = ((DynamicFluidStateProvider)state.getBlock()).getFluidState(state, world, pos); cir.setReturnValue(fluidState); cir.cancel(); } diff --git a/src/main/java/net/shadowfacts/extrahoppers/util/DynamicFluidStateProvider.java b/src/main/java/net/shadowfacts/extrahoppers/util/DynamicFluidStateProvider.java new file mode 100644 index 0000000..5e3f218 --- /dev/null +++ b/src/main/java/net/shadowfacts/extrahoppers/util/DynamicFluidStateProvider.java @@ -0,0 +1,27 @@ +package net.shadowfacts.extrahoppers.util; + +import net.minecraft.block.BlockState; +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.World; +import org.jetbrains.annotations.NotNull; + +/** + * @author shadowfacts + */ +public interface DynamicFluidStateProvider { + FluidState getFluidState(@NotNull BlockState state, @NotNull BlockView world, @NotNull BlockPos pos); + + @NotNull + FlowResult allowsFlow(@NotNull Direction toSide, @NotNull BlockState state, @NotNull BlockView world, @NotNull BlockPos pos); + + void setEmptyFluid(@NotNull World world, @NotNull BlockPos pos); + + enum FlowResult { + ALLOW, + DENY, + DEFAULT + } +} diff --git a/src/main/java/net/shadowfacts/extrahoppers/util/FluidFlowControllable.java b/src/main/java/net/shadowfacts/extrahoppers/util/FluidFlowControllable.java deleted file mode 100644 index b8ecec0..0000000 --- a/src/main/java/net/shadowfacts/extrahoppers/util/FluidFlowControllable.java +++ /dev/null @@ -1,23 +0,0 @@ -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 - } - -} diff --git a/src/main/java/net/shadowfacts/extrahoppers/util/PositionedFluidStateProvider.java b/src/main/java/net/shadowfacts/extrahoppers/util/PositionedFluidStateProvider.java deleted file mode 100644 index c1d5678..0000000 --- a/src/main/java/net/shadowfacts/extrahoppers/util/PositionedFluidStateProvider.java +++ /dev/null @@ -1,14 +0,0 @@ -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); -} diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/grate/GrateBlock.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/grate/GrateBlock.kt index 96a9dfe..1c65188 100644 --- a/src/main/kotlin/net/shadowfacts/extrahoppers/block/grate/GrateBlock.kt +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/grate/GrateBlock.kt @@ -17,9 +17,9 @@ 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.FluidFlowControllable -import net.shadowfacts.extrahoppers.util.PositionedFluidStateProvider +import net.shadowfacts.extrahoppers.util.DynamicFluidStateProvider /** * @author shadowfacts @@ -30,7 +30,7 @@ class GrateBlock: BlockWithEntity( .sounds(BlockSoundGroup.METAL) .nonOpaque() .build() -), PositionedFluidStateProvider, FluidFlowControllable, FluidFillable, FluidDrainable { +), DynamicFluidStateProvider, FluidFillable, FluidDrainable { companion object { val ID = Identifier("extrahoppers", "grate") @@ -79,10 +79,30 @@ class GrateBlock: BlockWithEntity( 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 + 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 @@ -94,11 +114,14 @@ class GrateBlock: BlockWithEntity( 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) { - be.fluidState = fluidState world.fluidTickScheduler.schedule(pos, fluidState.fluid, fluidState.fluid.getTickRate(world)) be.sync() } + if (world is World) { + triggerFluidUpdate(world, pos, state) + } true } else { false @@ -109,10 +132,13 @@ class GrateBlock: BlockWithEntity( 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.fluidState = null be.sync() } + if (world is World) { + triggerFluidUpdate(world, pos, state) + } fluidState.fluid } else { Fluids.EMPTY diff --git a/src/main/kotlin/net/shadowfacts/extrahoppers/block/grate/GrateBlockEntity.kt b/src/main/kotlin/net/shadowfacts/extrahoppers/block/grate/GrateBlockEntity.kt index 5b70d6f..6fce2e5 100644 --- a/src/main/kotlin/net/shadowfacts/extrahoppers/block/grate/GrateBlockEntity.kt +++ b/src/main/kotlin/net/shadowfacts/extrahoppers/block/grate/GrateBlockEntity.kt @@ -24,8 +24,10 @@ class GrateBlockEntity: BlockEntity(EHBlockEntities.GRATE), BlockEntityClientSer override fun fromTag(tag: CompoundTag) { super.fromTag(tag) - if (tag.contains("fluid", NbtType.COMPOUND)) { - fluidState = NbtHelper.toBlockState(tag.getCompound("fluid")).fluidState + fluidState = if (tag.contains("fluid", NbtType.COMPOUND)) { + NbtHelper.toBlockState(tag.getCompound("fluid")).fluidState + } else { + null } } @@ -37,9 +39,12 @@ class GrateBlockEntity: BlockEntity(EHBlockEntities.GRATE), BlockEntityClientSer } override fun fromClientTag(tag: CompoundTag) { - if (tag.contains("fluid", NbtType.COMPOUND)) { - fluidState = NbtHelper.toBlockState(tag.getCompound("fluid")).fluidState + fluidState = if (tag.contains("fluid", NbtType.COMPOUND)) { + NbtHelper.toBlockState(tag.getCompound("fluid")).fluidState + } else { + null } + world?.updateListeners(pos, cachedState, cachedState, 3) } } diff --git a/src/main/resources/extrahoppers.mixins.json b/src/main/resources/extrahoppers.mixins.json index 2ee09a2..eb66ebb 100644 --- a/src/main/resources/extrahoppers.mixins.json +++ b/src/main/resources/extrahoppers.mixins.json @@ -3,8 +3,9 @@ "package": "net.shadowfacts.extrahoppers.mixin", "compatibilityLevel": "JAVA_8", "mixins": [ - "MixinWorldChunk", - "MixinBaseFluid" + "MixinBaseFluid", + "MixinBucketItem", + "MixinWorldChunk" ], "client": [ ],