fix: 碎冰规则改为只保留水源变碎冰,流动水不再中断水流
原实现直接拦截 setBlockAndUpdate 并返回 false,导致邻接蓝冰的流动水被 shouldSpreadLiquid 的 return false 短路,水流扩散停止。 改为在 BlockState#is(BLUE_ICE) 判断处做手脚:规则开启且当前水非水源时让 is 返回 false,原版整个变碎冰分支被跳过,shouldSpreadLiquid 正常返回 true,水流照常扩散。
This commit is contained in:
1 parent
94fafe972c
commit
61ce9891b9
1 file changed
+41
-22
+41
-22
@@ -8,10 +8,12 @@ import net.minecraft.world.level.Level;
|
|||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.LiquidBlock;
|
import net.minecraft.world.level.block.LiquidBlock;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.material.FlowingFluid;
|
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
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.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 26.4 快照加入的“碎冰”(Brittle Ice)机制:
|
* 26.4 快照加入的“碎冰”(Brittle Ice)机制:
|
||||||
@@ -19,32 +21,49 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
* 会把当前水流方块替换为碎冰。
|
* 会把当前水流方块替换为碎冰。
|
||||||
*
|
*
|
||||||
* 开启 noBrittleIceFromFlowingWater 规则后:
|
* 开启 noBrittleIceFromFlowingWater 规则后:
|
||||||
* 仅当当前水方块处于“下落”状态(FlowingFluid#isFalling,即非水源且流体等级=8)时,
|
* 只有「水源方块」贴蓝冰时照常变碎冰;所有「流动的水」(横向、下落)都不再变碎冰,
|
||||||
* 才允许它被替换为碎冰;纯横向流动的水不再触发该替换,以保护蓝冰水道。
|
* 且水流扩散不受影响。
|
||||||
*
|
*
|
||||||
* 实现方式:用 WrapOperation 包住 shouldSpreadLiquid 里对 Level#setBlockAndUpdate 的调用,
|
* 实现:原版判断邻居是不是蓝冰用 BlockState#is(Blocks.BLUE_ICE),一旦命中就
|
||||||
* 只在「目标方块是 BRITTLE_ICE」且「当前水不是下落状态」时跳过该次设置,其余调用原样放行。
|
* 变碎冰并 return false(中断扩散)。本 mixin 让流动水贴蓝冰时这次 is() 返回 false,
|
||||||
|
* 整个“变碎冰”分支被跳过,shouldSpreadLiquid 正常返回 true,水流照常扩散。
|
||||||
|
* 位置信息通过 ThreadLocal 从方法入口传入。
|
||||||
*/
|
*/
|
||||||
@Mixin(LiquidBlock.class)
|
@Mixin(LiquidBlock.class)
|
||||||
public class MixinFlowingWaterBrittleIce {
|
public class MixinFlowingWaterBrittleIce {
|
||||||
@WrapOperation(
|
@Unique
|
||||||
method = "shouldSpreadLiquid",
|
private static final ThreadLocal<Level> CURRENT_LEVEL = new ThreadLocal<>();
|
||||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z")
|
@Unique
|
||||||
)
|
private static final ThreadLocal<BlockPos> CURRENT_POS = new ThreadLocal<>();
|
||||||
private boolean wrapSetBlockAndUpdate(Level level, BlockPos pos, BlockState newState,
|
|
||||||
Operation<Boolean> original) {
|
@Inject(method = "shouldSpreadLiquid", at = @At("HEAD"))
|
||||||
if (SLSCarpetSettings.noBrittleIceFromFlowingWater
|
private void captureArgs(Level level, BlockPos pos, BlockState state, CallbackInfoReturnable<Boolean> cir) {
|
||||||
&& newState.is(Blocks.BRITTLE_ICE)) {
|
CURRENT_LEVEL.set(level);
|
||||||
FluidState current = level.getFluidState(pos);
|
CURRENT_POS.set(pos);
|
||||||
if (!isFalling(current)) {
|
|
||||||
return false; // 跳过把这块水替换成碎冰
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return original.call(level, pos, newState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isFalling(FluidState fluid) {
|
@WrapOperation(
|
||||||
if (!(fluid.getType() instanceof FlowingFluid flowing)) return false;
|
method = "shouldSpreadLiquid",
|
||||||
return flowing.isFalling(fluid);
|
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<Boolean> 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user