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.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.DynamicFluidStateProvider; /** * @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 DynamicFluidStateProvider) { return ((DynamicFluidStateProvider)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 cir) { DynamicFluidStateProvider.FlowResult result = DynamicFluidStateProvider.FlowResult.DEFAULT; if (state.getBlock() instanceof DynamicFluidStateProvider) { result = ((DynamicFluidStateProvider)state.getBlock()).allowsFlow(direction, state, world, pos); } if (result != DynamicFluidStateProvider.FlowResult.DENY && fromState.getBlock() instanceof DynamicFluidStateProvider) { result = ((DynamicFluidStateProvider)fromState.getBlock()).allowsFlow(direction, fromState, world, fromPos); } 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); }