From 0649034969646cfacf929bb24eee43be868c39b5 Mon Sep 17 00:00:00 2001 From: Ap_Tx <3045929398@qq.com> Date: Sun, 4 Oct 2026 18:56:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=90=BD=E6=B2=99=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E6=94=B9=E7=94=A8=E8=AE=B0=E5=BD=95+=E5=9B=9E=E6=94=BE?= =?UTF-8?q?=EF=BC=88=E8=A3=85=E7=BD=AE=E9=A9=B1=E5=8A=A8=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 26.1.2单线程下1.12的替换窗口物理不存在,改用LegacyBlockChangeRecorder记录最近方块变更,fall时若命中窗口则用记录的新方块,保留装置驱动玩法。新增LevelChunkMixin记录setBlockState。 --- .../mixin/legacy/FallingBlockEntityMixin.java | 32 ++++----- .../mixin/legacy/LevelChunkMixin.java | 35 ++++++++++ .../util/LegacyBlockChangeRecorder.java | 70 +++++++++++++++++++ src/main/resources/slsaddition.mixins.json | 1 + 4 files changed, 119 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/github/zly2006/carpetslsaddition/mixin/legacy/LevelChunkMixin.java create mode 100644 src/main/java/com/github/zly2006/carpetslsaddition/util/LegacyBlockChangeRecorder.java diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/legacy/FallingBlockEntityMixin.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/legacy/FallingBlockEntityMixin.java index 11f4e46..81b9c6c 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/legacy/FallingBlockEntityMixin.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/legacy/FallingBlockEntityMixin.java @@ -1,25 +1,23 @@ package com.github.zly2006.carpetslsaddition.mixin.legacy; import com.github.zly2006.carpetslsaddition.SLSCarpetSettings; +import com.github.zly2006.carpetslsaddition.util.LegacyBlockChangeRecorder; import net.minecraft.core.BlockPos; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.Identifier; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyVariable; /** - * [旧版] 落沙替换的核心注入点。 + * [旧版] 落沙替换的核心注入点——重建 1.12 的"替换窗口"(记录+回放版)。 * - *
26.1.2 的 {@code FallingBlockEntity.fall(Level, BlockPos, BlockState)} 直接使用传入的 state, - * 不像 1.12 那样在构造实体时重新读取世界。本 mixin 用 {@link ModifyVariable} 拦截该 state 参数: - * 当 {@code legacyFallingBlockReplace} 开启且配置了目标方块时,把 state 替换为目标方块的默认状态。 + *
1.12:{@code BlockFalling} 创建实体时【重读世界】,异步线程在"检查→读取"间改块即可替换。 + * 26.1.2 单线程下该窗口物理不存在(tick 内同步 fall,无让出)。 * - *
等价于 1.12 在"检查可下落"与"读取方块状态"之间的窗口替换效果——最终得到一个 - * "装着目标方块"的下落实体,落地后即还原为该目标方块。 + *
本 mixin 改用 {@link LegacyBlockChangeRecorder}: + * 当 {@code legacyFallingBlockReplace} 开启时,若该位置在最近 {@code WINDOW_TICKS} 内被改动过, + * 就用记录的新方块作为下落实体的内容。这样玩家搭建的装置(改变世界方块)会决定下落实体的内容, + * 与 1.12 的"装置驱动"玩法一致。 */ @Mixin(net.minecraft.world.entity.item.FallingBlockEntity.class) public class FallingBlockEntityMixin { @@ -30,18 +28,14 @@ public class FallingBlockEntityMixin { argsOnly = true, index = 2 ) - private static BlockState legacyReplaceFallingState(BlockState original) { + private static BlockState legacyReplaceFallingState(BlockState original, net.minecraft.world.level.Level level, BlockPos pos, BlockState state) { if (!SLSCarpetSettings.legacyExploitMode || !SLSCarpetSettings.legacyFallingBlockReplace) { return original; } - String target = SLSCarpetSettings.legacyFallingBlockTarget; - if (target == null || target.isEmpty() || "#none".equals(target)) { - return original; + BlockState recent = LegacyBlockChangeRecorder.getRecentChange(pos); + if (recent != null && !recent.isAir()) { + return recent; } - Block block = BuiltInRegistries.BLOCK.getOptional(Identifier.withDefaultNamespace(target)).orElse(null); - if (block == null) { - return original; - } - return block.defaultBlockState(); + return original; } } \ No newline at end of file diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/legacy/LevelChunkMixin.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/legacy/LevelChunkMixin.java new file mode 100644 index 0000000..7143330 --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/legacy/LevelChunkMixin.java @@ -0,0 +1,35 @@ +package com.github.zly2006.carpetslsaddition.mixin.legacy; + +import com.github.zly2006.carpetslsaddition.SLSCarpetSettings; +import com.github.zly2006.carpetslsaddition.util.LegacyBlockChangeRecorder; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.LevelChunk; +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.callback.CallbackInfoReturnable; + +/** + * [旧版] 方块变更记录——为"替换窗口"提供数据源。 + * + *
hook {@link LevelChunk#setBlockState}:当规则开启时,记录每次方块变更(位置 + 新状态 + 当前 tick)。 + * 重力方块下落时({@code FallingBlockEntityMixin})会查询此记录, + * 若该位置"刚被改过",就用记录的新方块作为下落实体内容——重建 1.12 的窗口替换效果。 + * + *
仅在 {@code legacyExploitMode} + {@code legacyFallingBlockReplace} 同时开启时记录,避免性能损耗。
+ */
+@Mixin(LevelChunk.class)
+public abstract class LevelChunkMixin {
+
+ @Inject(method = "setBlockState", at = @At("RETURN"))
+ private void legacyRecordBlockChange(BlockPos pos, BlockState newState, int flags, CallbackInfoReturnable 1.12 的窗口依赖"异步线程在主线程 tick 中途改块",26.1.2 单线程模型下物理不存在。
+ * 本类改用"记录+回放":把最近发生的方块变更记录在此,
+ * 当重力方块触发下落时,若该位置"刚被改过",就用记录的新方块作为下落实体的内容——
+ * 等价于 1.12 的窗口替换效果(只是窗口由 mod 主动开启)。
+ *
+ * 记录以"服务器 tick 数"为界:仅保留最近 {@link #WINDOW_TICKS} 个 tick 内的变更,
+ * 超过即失效,避免记录无限增长或误伤无关方块。
+ */
+public final class LegacyBlockChangeRecorder {
+
+ private LegacyBlockChangeRecorder() {}
+
+ /** 窗口大小:变更与下落之间允许的最大 tick 间隔。 */
+ public static final long WINDOW_TICKS = 2L;
+
+ private record Change(BlockState state, long tick) {}
+
+ private static final Map