Author SHA1 Message Date
AxTps 01dc9fa79c feat: 落沙替换改回固定目标版,移除记录器mixin
build / build (push) Has been cancelled
记录+回放方案会把沙子替换成自己(记录命中沙子自身变更),不可用。改为沙子下落直接变legacyFallingBlockTarget。移除LevelChunkMixin。
2026-10-04 20:36:57 +08:00
AxTps a32a784f87 chore: 加调试日志定位instantFall/落沙替换未生效问题 2026-10-04 20:27:50 +08:00
AxTps 0649034969 feat: 落沙替换改用记录+回放(装置驱动)
26.1.2单线程下1.12的替换窗口物理不存在,改用LegacyBlockChangeRecorder记录最近方块变更,fall时若命中窗口则用记录的新方块,保留装置驱动玩法。新增LevelChunkMixin记录setBlockState。
2026-10-04 18:56:50 +08:00
AxTps c42fffad3c feat: instantFall改用ModifyArg直接改scheduleTick的delay参数
getDelayAfterPlace的hook可能被子类覆盖,改用ModifyArg拦截onPlace/updateShape的scheduleTick调用更可靠。
2026-10-04 18:06:05 +08:00
AxTps 21f8e92f2e feat: 实现instantFall(getDelayAfterPlace返回0) 2026-10-04 18:00:58 +08:00
AxTps 9963664933 fix: [旧版]分类字符串改用ASCII的legacy,中文仅作显示名
中文分类名会导致/carpet list命令报拖尾数据错误。
2026-10-04 17:33:07 +08:00
AxTps ddb8699328 fix: 修正[旧版]分类的lang key为carpet.category.旧版
Carpet分类的lang key直接使用分类字符串本身,而非小写常量名。
2026-10-04 17:29:47 +08:00
AxTps ff742f0274 feat: 复刻1.12遗留漏洞机制(旧版分类)
build / build (push) Has been cancelled
新增[旧版]Carpet分类及7条规则,完整复刻1.12获取非法方块所需机制:

- legacyInstantFall/legacyInstantTick:等价1.12的瞬间下落/计划刻立即执行

- legacyAsyncChunkAccess:自建后台线程模拟1.12信标线程并发访问区块

- legacyChunkSwap:hook getVisibleChunkIfPresent,异步线程伪装区块未加载触发装饰

- legacyFallingBlockReplace/legacyFallingBlockTarget:拦截fall的state参数实现落沙替换

参考1.12源码(MCP反编译)+Earthcomputer/Myren的原理讲解实现。
2026-10-04 17:06:20 +08:00
12 changed files with 548 additions and 2 deletions

No files matched your search

@@ -7,6 +7,7 @@ public class SLSCarpetSettings {
public static final String NEED_CLIENT = "needClient"; // 需要客户端安装SLS-Addition或实现相关支持 public static final String NEED_CLIENT = "needClient"; // 需要客户端安装SLS-Addition或实现相关支持
public static final String FROM_AMS = "AMS"; public static final String FROM_AMS = "AMS";
public static final String SLSA = "SLS"; public static final String SLSA = "SLS";
public static final String LEGACY = "legacy";
@Rule(categories = {SLSA, RuleCategory.SURVIVAL}) @Rule(categories = {SLSA, RuleCategory.SURVIVAL})
public static boolean obtainableReinforcedDeepSlate = false; public static boolean obtainableReinforcedDeepSlate = false;
@@ -77,4 +78,32 @@ public class SLSCarpetSettings {
@Rule(categories = {SLSA, RuleCategory.FEATURE}) @Rule(categories = {SLSA, RuleCategory.FEATURE})
public static boolean unbreakableDecoratedPot = false; public static boolean unbreakableDecoratedPot = false;
// ===== [旧版] 遗留漏洞机制复刻 =====
// 总开关:开启后,其余子规则才生效
@Rule(categories = {LEGACY}, strict = false)
public static boolean legacyExploitMode = false;
// 等价 instantTick:计划刻(scheduleTick)立即执行,不等延迟
@Rule(categories = {LEGACY})
public static boolean legacyInstantTick = false;
// 等价 instantFall:重力方块被计划刻触发时立即下落
@Rule(categories = {LEGACY})
public static boolean legacyInstantFall = false;
// 自建后台线程,模拟 1.12 信标线程并发访问 chunk
@Rule(categories = {LEGACY})
public static boolean legacyAsyncChunkAccess = false;
// 允许异步线程在 chunk 表竞态时把"已加载"当成"未加载",触发重新加载/装饰
@Rule(categories = {LEGACY})
public static boolean legacyChunkSwap = false;
// 落沙替换:在 FallingBlock 转实体窗口内把方块替换成目标方块
@Rule(categories = {LEGACY})
public static boolean legacyFallingBlockReplace = false;
// 目标方块(替换结果),默认末地传送门框架
@Rule(categories = {LEGACY}, strict = false, options = {"#none", "end_portal_frame", "command_block", "spawner", "barrier", "nether_portal"})
public static String legacyFallingBlockTarget = "#none";
} }
@@ -51,6 +51,34 @@ public class ServerMain implements ModInitializer, CarpetExtension {
@Override @Override
public void onServerLoaded(MinecraftServer server) { public void onServerLoaded(MinecraftServer server) {
ServerMain.server = server; ServerMain.server = server;
startLegacyRuleWatcher();
}
/** [旧版] 轮询规则状态,按需启停异步 chunk 线程。 */
private void startLegacyRuleWatcher() {
Thread watcher = new Thread(() -> {
boolean running = false;
while (!Thread.currentThread().isInterrupted()) {
try {
boolean want = SLSCarpetSettings.legacyExploitMode
&& SLSCarpetSettings.legacyAsyncChunkAccess;
if (want && !running) {
com.github.zly2006.carpetslsaddition.util.LegacyAsyncExecutor.start();
running = true;
} else if (!want && running) {
com.github.zly2006.carpetslsaddition.util.LegacyAsyncExecutor.stop();
running = false;
}
Thread.sleep(1000L);
} catch (InterruptedException e) {
return;
} catch (Throwable t) {
LOGGER.debug("[SLSA] legacy rule watcher error: {}", t.toString());
}
}
}, "SLSA-Legacy-RuleWatcher");
watcher.setDaemon(true);
watcher.start();
} }
@Override @Override
@@ -0,0 +1,56 @@
package com.github.zly2006.carpetslsaddition.mixin.legacy;
import com.github.zly2006.carpetslsaddition.SLSCarpetSettings;
import com.github.zly2006.carpetslsaddition.ServerMain;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
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;
/**
* [旧版] 区块替换(chunk swap)——race condition 的等价实现。
*
* <p>1.12 的漏洞:{@code ChunkProviderServer.id2ChunkMap}(非线程安全的
* {@code Long2ObjectOpenHashMap})被主线程 {@code remove}(卸载)与异步线程 {@code get}
* 并发访问,导致 {@code get} 错过已加载的区块,进而触发"重新加载 + 世界装饰"。
*
* <p>26.1.2 已用 {@code Long2ObjectLinkedOpenHashMap} + {@code mainThreadExecutor} 约束修复。
* 直接并发改 map 风险极高(可能崩溃/损坏存档),故本 mixin 采用<b>低风险等价方案</b>:
* hook {@link ChunkMap#getVisibleChunkIfPresent(long)},当满足以下条件时对<b>非主线程</b>调用返回 {@code null}:
* <ul>
* <li>{@code legacyExploitMode} + {@code legacyChunkSwap} 均开启</li>
* <li>当前不是服务器主线程(即异步线程在访问)</li>
* </ul>
* 这样异步线程会"误以为区块未加载",后续逻辑会尝试重新加载并触发世界装饰,
* 从而在异步线程上产生方块更新——与 1.12 的效果等价,但不触碰共享数据结构。
*
* <p><b>⚠ 风险</b>:仍可能引起区块状态不一致。仅在明确开启时生效。
*/
@Mixin(ChunkMap.class)
public abstract class ChunkMapMixin {
@Inject(method = "getVisibleChunkIfPresent", at = @At("RETURN"), cancellable = true)
private void legacyChunkSwap(long chunkPos, CallbackInfoReturnable<ChunkHolder> cir) {
if (cir.getReturnValue() == null) {
return;
}
if (!SLSCarpetSettings.legacyExploitMode || !SLSCarpetSettings.legacyChunkSwap) {
return;
}
// 仅在异步线程访问时伪装"区块未加载"
if (!isServerMainThread()) {
cir.setReturnValue(null);
}
}
/** 判断当前是否在服务器主线程上。 */
private static boolean isServerMainThread() {
net.minecraft.server.MinecraftServer server = ServerMain.server;
if (server == null) {
return true;
}
return server.isSameThread();
}
}
@@ -0,0 +1,46 @@
package com.github.zly2006.carpetslsaddition.mixin.legacy;
import com.github.zly2006.carpetslsaddition.SLSCarpetSettings;
import com.github.zly2006.carpetslsaddition.ServerMain;
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;
/**
* [旧版] 落沙替换——固定目标版。
*
* <p>26.1.2 单线程下 1.12 的"替换窗口"物理不存在,本 mixin 采用直接方案:
* 当 {@code legacyFallingBlockReplace} 开启且配置了 {@code legacyFallingBlockTarget} 时,
* 把下落实体的方块状态替换为目标方块的默认状态——沙子下落即变目标方块。
*/
@Mixin(net.minecraft.world.entity.item.FallingBlockEntity.class)
public class FallingBlockEntityMixin {
@ModifyVariable(
method = "fall",
at = @At("HEAD"),
argsOnly = true,
index = 2
)
private static BlockState legacyReplaceFallingState(BlockState original, 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;
}
Block block = BuiltInRegistries.BLOCK.getOptional(Identifier.withDefaultNamespace(target)).orElse(null);
if (block == null) {
return original;
}
ServerMain.LOGGER.info("[SLSA-DEBUG] >>> REPLACE at {}: {} -> {}", pos, original.getBlock(), block);
return block.defaultBlockState();
}
}
@@ -0,0 +1,78 @@
package com.github.zly2006.carpetslsaddition.mixin.legacy;
import com.github.zly2006.carpetslsaddition.SLSCarpetSettings;
import com.github.zly2006.carpetslsaddition.util.LegacyExploitState;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.FallingBlock;
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.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/**
* [旧版] 瞬间下落(等价 1.12 的 instantFall flag)。
*
* <p>1.12:世界装饰时短暂开启 instantFall,使重力方块在被更新时【立即】转为下落实体,
* 而不等待 2gt 的计划刻延迟。26.1.2 已移除该 flag。
*
* <p>实现方式(双保险):
* <ul>
* <li>{@link #legacyDelayAfterPlace}:把 {@code getDelayAfterPlace()} 的返回值改为 0。</li>
* <li>{@link #legacyScheduleDelay}:直接拦截 {@code onPlace}/{@code updateShape} 里
* 对 {@code scheduleTick} 的 delay 参数,强制改为 0(更直接可靠)。</li>
* </ul>
*/
@Mixin(FallingBlock.class)
public abstract class FallingBlockMixin {
/** instantFall:把"放置后延迟"改为 0。 */
@Inject(method = "getDelayAfterPlace", at = @At("HEAD"), cancellable = true)
private void legacyDelayAfterPlace(CallbackInfoReturnable<Integer> cir) {
if (SLSCarpetSettings.legacyExploitMode && SLSCarpetSettings.legacyInstantFall) {
cir.setReturnValue(0);
}
}
/**
* instantFall:拦截 onPlace / updateShape 里 scheduleTick 的 delay 参数,强制为 0。
* 第 3 个参数(index=2)是延迟 tick 数。
*/
@ModifyArg(
method = "onPlace",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/level/Level;scheduleTick(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;I)V"),
index = 2
)
private int legacyScheduleDelayLevel(int delay) {
if (SLSCarpetSettings.legacyExploitMode && SLSCarpetSettings.legacyInstantFall) {
return 0;
}
return delay;
}
@ModifyArg(
method = "updateShape",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/level/ScheduledTickAccess;scheduleTick(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;I)V"),
index = 2
)
private int legacyScheduleDelayAccess(int delay) {
if (SLSCarpetSettings.legacyExploitMode && SLSCarpetSettings.legacyInstantFall) {
return 0;
}
return delay;
}
/** instantFall:tick 入口标记(供其他机制判断窗口)。 */
@Inject(method = "tick", at = @At("HEAD"))
private void legacyTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource rand, CallbackInfo ci) {
if (SLSCarpetSettings.legacyExploitMode && SLSCarpetSettings.legacyInstantFall) {
LegacyExploitState.markInstantFall(pos);
}
}
}
@@ -0,0 +1,32 @@
package com.github.zly2006.carpetslsaddition.mixin.legacy;
import com.github.zly2006.carpetslsaddition.SLSCarpetSettings;
import net.minecraft.world.ticks.ScheduledTick;
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;
/**
* [旧版] 计划刻立即执行(等价 1.12 的 instantTick flag)。
*
* <p>1.12 的 instantTick:世界装饰时会短暂开启,使计划刻(中继器、发射器、沙子等)
* 立即执行而不等待延迟。26.1.2 已移除该 flag。
*
* <p>本 mixin 用 {@link Inject} 拦截 {@link ScheduledTick#triggerTick()}:
* 规则开启时返回 0,使该计划刻在"当前时刻"被触发(等价立即执行)。
*
* <p><b>注意</b>:这会强制所有计划刻立即触发,可能造成大量连锁更新,
* 仅应在 {@code legacyExploitMode} + {@code legacyInstantTick} 同时开启时使用。
*/
@Mixin(ScheduledTick.class)
public abstract class ScheduledTickMixin {
@Inject(method = "triggerTick", at = @At("HEAD"), cancellable = true)
private void legacyInstantTriggerTick(CallbackInfoReturnable<Long> cir) {
if (SLSCarpetSettings.legacyExploitMode && SLSCarpetSettings.legacyInstantTick) {
// 返回 0 表示"在当前时刻立即触发"
cir.setReturnValue(0L);
}
}
}
@@ -0,0 +1,105 @@
package com.github.zly2006.carpetslsaddition.util;
import com.github.zly2006.carpetslsaddition.ServerMain;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.LevelChunk;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* [旧版] 自建异步线程,模拟 1.12 的"染色玻璃→信标搜索线程"。
*
* <p>1.12 的漏洞依赖一个独立的异步线程,与主线程并发访问区块哈希表
* ({@code Long2ObjectOpenHashMap}),从而制造 race condition,让 chunk 被误判为"未加载",
* 触发重新加载与世界装饰。
*
* <p>26.1.2 的信标已无独立线程,故本类自建一个单线程调度器:
* 周期性在<b>主线程之外</b>调用 {@link ServerChunkCache#getChunkNow} 与读取区块,
* 尽最大可能复现 1.12 的并发访问模式。
*
* <p><b>⚠ 风险提示</b>:26.1.2 的区块访问有 {@code mainThreadExecutor} 约束,
* 跨线程访问可能触发断言或未定义行为,极端情况下可导致服务器崩溃或存档损坏。
* 仅在 {@code legacyExploitMode} + {@code legacyAsyncChunkAccess} 同时开启时启动。
*/
public final class LegacyAsyncExecutor {
private LegacyAsyncExecutor() {}
private static ScheduledExecutorService executor;
private static volatile boolean started = false;
/** 目标区块坐标(由玩家装置或命令设置)。 */
private static volatile int targetChunkX = Integer.MIN_VALUE;
private static volatile int targetChunkZ = Integer.MIN_VALUE;
public static void setTargetChunk(int x, int z) {
targetChunkX = x;
targetChunkZ = z;
}
public static synchronized void start() {
if (started) {
return;
}
executor = Executors.newSingleThreadScheduledExecutor(r -> {
Thread t = new Thread(r, "SLSA-Legacy-AsyncChunk");
t.setDaemon(true);
return t;
});
executor.scheduleAtFixedRate(LegacyAsyncExecutor::tick, 0, 1, TimeUnit.MILLISECONDS);
started = true;
LegacyExploitState.setAsyncThreadRunning(true);
ServerMain.LOGGER.info("[SLSA] legacy async chunk thread started");
}
public static synchronized void stop() {
if (!started || executor == null) {
return;
}
executor.shutdownNow();
executor = null;
started = false;
LegacyExploitState.setAsyncThreadRunning(false);
ServerMain.LOGGER.info("[SLSA] legacy async chunk thread stopped");
}
/** 异步线程主体:并发访问目标区块,制造与主线程的竞态。 */
private static void tick() {
try {
if (!SLSCarpetSettingsBridge.shouldRun()) {
return;
}
MinecraftServer server = ServerMain.server;
if (server == null) {
return;
}
for (ServerLevel level : server.getAllLevels()) {
ServerChunkCache cache = level.getChunkSource();
if (targetChunkX != Integer.MIN_VALUE) {
// 故意在主线程之外读取区块表——制造 race condition
LevelChunk chunk = cache.getChunkNow(targetChunkX, targetChunkZ);
if (chunk != null) {
// 触发一次方块状态读取,模拟信标向下搜索
chunk.getBlockState(new net.minecraft.core.BlockPos(
targetChunkX << 4, level.getMinY(), targetChunkZ << 4));
}
}
}
} catch (Throwable t) {
// 异步线程绝不能让异常冒泡导致调度器静默停止
ServerMain.LOGGER.debug("[SLSA] legacy async tick error: {}", t.toString());
}
}
/** 桥接类:避免直接依赖 SLSCarpetSettings 的静态初始化顺序问题。 */
private static final class SLSCarpetSettingsBridge {
static boolean shouldRun() {
return com.github.zly2006.carpetslsaddition.SLSCarpetSettings.legacyExploitMode
&& com.github.zly2006.carpetslsaddition.SLSCarpetSettings.legacyAsyncChunkAccess;
}
}
}
@@ -0,0 +1,70 @@
package com.github.zly2006.carpetslsaddition.util;
import com.github.zly2006.carpetslsaddition.ServerMain;
import net.minecraft.core.BlockPos;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* [旧版] 方块变更记录器——用于重建 1.12 的"替换窗口"。
*
* <p>1.12 的窗口依赖"异步线程在主线程 tick 中途改块",26.1.2 单线程模型下物理不存在。
* 本类改用"记录+回放":把最近发生的方块变更记录在此,
* 当重力方块触发下落时,若该位置"刚被改过",就用记录的新方块作为下落实体的内容——
* 等价于 1.12 的窗口替换效果(只是窗口由 mod 主动开启)。
*
* <p>记录以"服务器 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<Long, Change> RECENT = new ConcurrentHashMap<>();
/** 获取当前服务器 tick(拿不到时回退为 0)。 */
private static long now() {
MinecraftServer server = ServerMain.server;
return server != null ? server.getTickCount() : 0L;
}
/** 记录一次方块变更。 */
public static void record(BlockPos pos, BlockState newState) {
RECENT.put(pos.asLong(), new Change(newState, now()));
}
/**
* 查询某位置是否在窗口期内有变更记录。
*
* @return 若命中窗口,返回记录的新状态;否则返回 null。
*/
public static BlockState getRecentChange(BlockPos pos) {
Change c = RECENT.get(pos.asLong());
if (c == null) {
return null;
}
if (now() - c.tick() > WINDOW_TICKS) {
RECENT.remove(pos.asLong());
return null;
}
return c.state();
}
/** 清理过期记录。 */
public static void cleanup() {
long t = now();
RECENT.entrySet().removeIf(e -> t - e.getValue().tick() > WINDOW_TICKS);
}
public static void clear() {
RECENT.clear();
}
}
@@ -0,0 +1,66 @@
package com.github.zly2006.carpetslsaddition.util;
import net.minecraft.core.BlockPos;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
/**
* [旧版] 漏洞机制的全局状态管理(线程安全)。
*
* <p>承载:
* <ul>
* <li>当前"落沙替换目标方块"ID(由 FallingBlockMixin 设置,FallingBlockEntityMixin 消费)</li>
* <li>被标记为 instantFall 触发的位置(跨线程共享,故用并发容器)</li>
* <li>异步 chunk 访问线程的运行状态</li>
* </ul>
*
* <p><b>线程安全说明</b>:本类会被主线程与自建的异步线程同时访问,
* 所有可变状态均使用并发容器或原子引用。
*/
public final class LegacyExploitState {
private LegacyExploitState() {}
/** 当前落沙替换目标(方块 ID 字符串),"#none" 表示禁用。 */
private static final AtomicReference<String> REPLACE_TARGET = new AtomicReference<>("#none");
/** 被标记为 instantFall 触发的位置集合(异步线程可读)。 */
private static final ConcurrentHashMap<Long, Boolean> INSTANT_FALL_POS = new ConcurrentHashMap<>();
/** 异步 chunk 访问线程是否正在运行。 */
private static volatile boolean asyncThreadRunning = false;
public static void setReplaceTarget(String target) {
REPLACE_TARGET.set(target == null ? "#none" : target);
}
public static String getReplaceTarget() {
return REPLACE_TARGET.get();
}
public static boolean hasReplaceTarget() {
String t = REPLACE_TARGET.get();
return t != null && !"#none".equals(t) && !t.isEmpty();
}
public static void markInstantFall(BlockPos pos) {
INSTANT_FALL_POS.put(pos.asLong(), Boolean.TRUE);
}
public static boolean isInstantFall(BlockPos pos) {
return INSTANT_FALL_POS.containsKey(pos.asLong());
}
public static void clearInstantFall(BlockPos pos) {
INSTANT_FALL_POS.remove(pos.asLong());
}
public static boolean isAsyncThreadRunning() {
return asyncThreadRunning;
}
public static void setAsyncThreadRunning(boolean running) {
asyncThreadRunning = running;
}
}
@@ -2,6 +2,7 @@
"carpet.category.pca": "PCA Adaption", "carpet.category.pca": "PCA Adaption",
"carpet.category.needClient":"Need client support", "carpet.category.needClient":"Need client support",
"carpet.category.protocol":"Protocol", "carpet.category.protocol":"Protocol",
"carpet.category.legacy": "Legacy",
"carpet.rule.obtainableReinforcedDeepSlate.name": "Obtainable reinforced deep slate", "carpet.rule.obtainableReinforcedDeepSlate.name": "Obtainable reinforced deep slate",
@@ -72,5 +73,20 @@
"carpet.slsa.bot.respawned": "The bot %s's online time has been reset.", "carpet.slsa.bot.respawned": "The bot %s's online time has been reset.",
"carpet.slsa.bot.not_a_bot": "The player %s is not created by carpet sls addition, so you can't reset the online time.", "carpet.slsa.bot.not_a_bot": "The player %s is not created by carpet sls addition, so you can't reset the online time.",
"carpet.slsa.block.deep_slate_core": "Deepslate Core" "carpet.slsa.block.deep_slate_core": "Deepslate Core",
"carpet.rule.legacyExploitMode.name": "Legacy exploit mode",
"carpet.rule.legacyExploitMode.desc": "Master switch: other rules under the [Legacy] category only take effect when enabled",
"carpet.rule.legacyInstantTick.name": "Instant scheduled tick",
"carpet.rule.legacyInstantTick.desc": "Equivalent to 1.12 instantTick: scheduled ticks execute immediately without delay",
"carpet.rule.legacyInstantFall.name": "Instant falling blocks",
"carpet.rule.legacyInstantFall.desc": "Equivalent to 1.12 instantFall: falling blocks fall immediately when scheduled",
"carpet.rule.legacyAsyncChunkAccess.name": "Async chunk access thread",
"carpet.rule.legacyAsyncChunkAccess.desc": "Spawns a background thread mimicking 1.12 beacon thread to access chunks concurrently",
"carpet.rule.legacyChunkSwap.name": "Chunk swap",
"carpet.rule.legacyChunkSwap.desc": "Allows async thread to treat a loaded chunk as unloaded via race condition, triggering reload and world population",
"carpet.rule.legacyFallingBlockReplace.name": "Falling block replace",
"carpet.rule.legacyFallingBlockReplace.desc": "Replaces the block with a target block during the falling block to entity window",
"carpet.rule.legacyFallingBlockTarget.name": "Falling replace target",
"carpet.rule.legacyFallingBlockTarget.desc": "Target block ID for falling block replace, #none to disable"
} }
@@ -2,6 +2,7 @@
"carpet.category.pca": "PCA适配", "carpet.category.pca": "PCA适配",
"carpet.category.needClient": "需要客户端支持", "carpet.category.needClient": "需要客户端支持",
"carpet.category.protocol": "协议", "carpet.category.protocol": "协议",
"carpet.category.legacy": "旧版",
"carpet.rule.obtainableReinforcedDeepSlate.name": "强化深板岩可获取", "carpet.rule.obtainableReinforcedDeepSlate.name": "强化深板岩可获取",
@@ -72,5 +73,20 @@
"carpet.slsa.bot.respawned": "假人%s的在线时长已重置!", "carpet.slsa.bot.respawned": "假人%s的在线时长已重置!",
"carpet.slsa.bot.not_a_bot": "假人%s不是由Carpet SLS Addition生成的,所以你不能重置它的在线时间!", "carpet.slsa.bot.not_a_bot": "假人%s不是由Carpet SLS Addition生成的,所以你不能重置它的在线时间!",
"carpet.slsa.block.deep_slate_core": "深板岩核心" "carpet.slsa.block.deep_slate_core": "深板岩核心",
"carpet.rule.legacyExploitMode.name": "旧版漏洞模式",
"carpet.rule.legacyExploitMode.desc": "总开关:开启后[旧版]分类下的其余机制规则才会生效",
"carpet.rule.legacyInstantTick.name": "计划刻立即执行",
"carpet.rule.legacyInstantTick.desc": "等价1.12的instantTick:计划刻(scheduleTick)立即执行而不等待延迟",
"carpet.rule.legacyInstantFall.name": "重力方块瞬间下落",
"carpet.rule.legacyInstantFall.desc": "等价1.12的instantFall:重力方块被计划刻触发时立即下落",
"carpet.rule.legacyAsyncChunkAccess.name": "异步区块访问线程",
"carpet.rule.legacyAsyncChunkAccess.desc": "自建后台线程模拟1.12的信标线程,并发访问区块",
"carpet.rule.legacyChunkSwap.name": "区块替换",
"carpet.rule.legacyChunkSwap.desc": "允许异步线程在区块表竞态时把已加载区块当成未加载,触发重新加载与世界装饰",
"carpet.rule.legacyFallingBlockReplace.name": "落沙替换",
"carpet.rule.legacyFallingBlockReplace.desc": "在重力方块转为下落实体的窗口内,把方块替换为指定目标方块",
"carpet.rule.legacyFallingBlockTarget.name": "落沙替换目标方块",
"carpet.rule.legacyFallingBlockTarget.desc": "落沙替换的目标方块ID,#none为禁用"
} }
@@ -16,6 +16,10 @@
"carpet.MixinPlayerCommand", "carpet.MixinPlayerCommand",
"elytra.ItemAccessor", "elytra.ItemAccessor",
"elytra.MixinItem", "elytra.MixinItem",
"legacy.FallingBlockMixin",
"legacy.FallingBlockEntityMixin",
"legacy.ScheduledTickMixin",
"legacy.ChunkMapMixin",
"entity.MixinArmadilloEntity", "entity.MixinArmadilloEntity",
"entity.MixinArmorStandEntity", "entity.MixinArmorStandEntity",
"entity.MixinBoatEntity", "entity.MixinBoatEntity",