diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinFlowingWaterBrittleIce.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinFlowingWaterBrittleIce.java index dc071fb..2d338b9 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinFlowingWaterBrittleIce.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/block/MixinFlowingWaterBrittleIce.java @@ -8,10 +8,12 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FlowingFluid; import net.minecraft.world.level.material.FluidState; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; /** * 26.4 快照加入的“碎冰”(Brittle Ice)机制: @@ -19,32 +21,49 @@ import org.spongepowered.asm.mixin.injection.At; * 会把当前水流方块替换为碎冰。 * * 开启 noBrittleIceFromFlowingWater 规则后: - * 仅当当前水方块处于“下落”状态(FlowingFluid#isFalling,即非水源且流体等级=8)时, - * 才允许它被替换为碎冰;纯横向流动的水不再触发该替换,以保护蓝冰水道。 + * 只有「水源方块」贴蓝冰时照常变碎冰;所有「流动的水」(横向、下落)都不再变碎冰, + * 且水流扩散不受影响。 * - * 实现方式:用 WrapOperation 包住 shouldSpreadLiquid 里对 Level#setBlockAndUpdate 的调用, - * 只在「目标方块是 BRITTLE_ICE」且「当前水不是下落状态」时跳过该次设置,其余调用原样放行。 + * 实现:原版判断邻居是不是蓝冰用 BlockState#is(Blocks.BLUE_ICE),一旦命中就 + * 变碎冰并 return false(中断扩散)。本 mixin 让流动水贴蓝冰时这次 is() 返回 false, + * 整个“变碎冰”分支被跳过,shouldSpreadLiquid 正常返回 true,水流照常扩散。 + * 位置信息通过 ThreadLocal 从方法入口传入。 */ @Mixin(LiquidBlock.class) public class MixinFlowingWaterBrittleIce { - @WrapOperation( - method = "shouldSpreadLiquid", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z") - ) - private boolean wrapSetBlockAndUpdate(Level level, BlockPos pos, BlockState newState, - Operation original) { - if (SLSCarpetSettings.noBrittleIceFromFlowingWater - && newState.is(Blocks.BRITTLE_ICE)) { - FluidState current = level.getFluidState(pos); - if (!isFalling(current)) { - return false; // 跳过把这块水替换成碎冰 - } - } - return original.call(level, pos, newState); + @Unique + private static final ThreadLocal CURRENT_LEVEL = new ThreadLocal<>(); + @Unique + private static final ThreadLocal CURRENT_POS = new ThreadLocal<>(); + + @Inject(method = "shouldSpreadLiquid", at = @At("HEAD")) + private void captureArgs(Level level, BlockPos pos, BlockState state, CallbackInfoReturnable cir) { + CURRENT_LEVEL.set(level); + CURRENT_POS.set(pos); } - private static boolean isFalling(FluidState fluid) { - if (!(fluid.getType() instanceof FlowingFluid flowing)) return false; - return flowing.isFalling(fluid); + @WrapOperation( + method = "shouldSpreadLiquid", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;is(Ljava/lang/Object;)Z") + ) + private boolean wrapIsBlueIce(BlockState instance, Object target, Operation original) { + Boolean result = original.call(instance, target); + if (!result) return false; + // 只有判断目标确实是 BLUE_ICE 时才可能干预 + if (!(target instanceof net.minecraft.world.level.block.Block b) || !b.equals(Blocks.BLUE_ICE)) { + return true; + } + if (!SLSCarpetSettings.noBrittleIceFromFlowingWater) return true; + + Level level = CURRENT_LEVEL.get(); + BlockPos pos = CURRENT_POS.get(); + if (level == null || pos == null) return true; + + FluidState current = level.getFluidState(pos); + // 流动水(非水源)不让它触发碎冰替换 + if (!current.isSource()) { + return false; + } + return true; } } \ No newline at end of file