You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用SpongePowered Mixins修改Minecraft Forge 1.18.2中LevelReader接口的isEmptyBlock方法?

如何使用SpongePowered Mixins修改Minecraft Forge 1.18.2中LevelReader接口的isEmptyBlock方法?

兄弟,你碰到的这个问题太常见了——LevelReader是个接口啊,它本身根本没有方法的具体实现,你直接Mixin接口的话,你的代码根本不会被执行,因为游戏运行时实际调用的是实现了这个接口的类的方法,比如Level或者ChunkLevel这些具体类。

给你两个靠谱的解决方案,你可以根据需求选:

方案一:Mixin接口的核心实现类(推荐)

最直接的方式就是找到LevelReader最常用的实现类,比如net.minecraft.world.level.Level——游戏里绝大多数场景下的LevelReader实例都是Level对象。你只需要把你的Mixin目标换成这个类,然后正常写注入逻辑就行。

修改后的代码示例:

package net.iateminecraft.jetpacksfix.mixin;

import com.mojang.logging.LogUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import org.slf4j.Logger;
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;

@Mixin(Level.class)
public abstract class MixinLevelReader implements LevelReader {
    @Unique
    private static final Logger LOGGER = LogUtils.getLogger();

    @Inject(method = "isEmptyBlock", at = @At("HEAD"), cancellable = true)
    private void modifyIsEmptyBlock(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
        // 这里写你的自定义逻辑,比如修改返回值
        // 举个例子:让空气方块也不算空(只是示例,你改成自己的需求)
        boolean customResult = !((Level)(Object)this).getBlockState(pos).isAir();
        cir.setReturnValue(customResult);
        LOGGER.info("修改了isEmptyBlock的返回值,位置{}:{}", pos, customResult);
    }
}

要是之后发现某些场景用的是其他实现类(比如ChunkLevel),你再给那个类写个对应的Mixin就行,逻辑和上面基本一致。

方案二:用@Overwrite直接替换方法实现

如果你想完全接管这个方法的逻辑,可以用@Overwrite注解,但要注意:这种方式容易和其他修改同方法的mod冲突,所以谨慎使用。

示例代码:

package net.iateminecraft.jetpacksfix.mixin;

import com.mojang.logging.LogUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.Overwrite;

@Mixin(Level.class)
public abstract class MixinLevelReader implements LevelReader {
    @Unique
    private static final Logger LOGGER = LogUtils.getLogger();

    @Overwrite
    public boolean isEmptyBlock(BlockPos pos) {
        // 这里写你的完整自定义逻辑
        // 要是需要调用原来的逻辑,得这么写(避免递归)
        boolean originalResult = ((Level)(Object)this).getBlockState(pos).isAir();
        // 加自己的判断条件
        boolean customResult = originalResult && pos.getY() > 64;
        LOGGER.info("原结果{},自定义结果{}", originalResult, customResult);
        return customResult;
    }
}

最后再提醒一句:千万别直接Mixin接口,接口只是个规范,没有实际执行的代码,你的修改根本落不了地。一定要找具体的实现类来Mixin才行!

备注:内容来源于stack exchange,提问作者I Ate Minecraft

火山引擎 最新活动