按 U 键启用愤怒模式时,Minecraft 崩溃

问题描述 投票:0回答:1

我马上就说,在日志中没有出现错误,我在minecraft 1.12.2中使用forge版本2859,我写了几个类,其中一个负责RageMode,本质是玩家在打开RageMode时应该飞到最近的实体并对其造成 200 点伤害,因此在 10 秒内再次,如果玩家遇到障碍物,他必须摧毁它们的碰撞箱。下一个类KeyInputHandler,它负责检查U键的按下情况,然后激活RageMode。有什么问题-进入游戏时一切正常,但是当你按U时游戏完全冻结,关闭它的唯一方法-它被强制关闭,查看日志没有任何错误记录,只是铭文退出游戏,代码为 0。

代码如下: 主文件

package daun.aut.utils;

import daun.aut.utils.Handlers.KeyInputHandler;
import daun.aut.recipes.SmeltingRecipes;
import daun.aut.tabs.autTab;
import daun.aut.utils.Handlers.RegistryHandler;
import daun.aut.utils.proxy.CommonProxy;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.Instance;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;



    @Mod(modid = Reference.MODID, name = Reference.NAME, version = Reference.VERSION)
    public class Main
    {
        public static final CreativeTabs autTab = new autTab("autismotab");

        @Instance
        public static Main instance;

        @SidedProxy(modId = Reference.MODID, clientSide= Reference.CLIENT, serverSide = Reference.COMMON)
        public static CommonProxy proxy;

        @EventHandler
        public static void preInit(FMLPreInitializationEvent event)
        {
            RegistryHandler.otherRegistries();
            KeyInputHandler.registerKeyBindings();

        }

        @EventHandler
        public static void Init(FMLInitializationEvent event) {
            SmeltingRecipes.init();
            MinecraftForge.EVENT_BUS.register(new CustomFog());
            MinecraftForge.EVENT_BUS.register(new KeyInputHandler());
        }

        @EventHandler
        public static void postInit(FMLPostInitializationEvent event) {
        }

    }

愤怒模式

package daun.aut.utils;

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;

public class RageMode {

    private EntityPlayer player;
    private World world;
    private long startTime;
    private final long duration = 10 * 20; // 10 seconds (20 ticks per second)
    private final double speed = 1.5; // Speed of movement

    public RageMode(EntityPlayer player) {
        this.player = player;
        this.world = player.world;
        this.startTime = world.getTotalWorldTime();
        activateRage();
    }

    private void activateRage() {
        while (world.getTotalWorldTime() < startTime + duration) {
            EntityLivingBase target = findNearestTarget();
            if (target != null) {
                moveTowards(target);
                attack(target);
                breakObstacles();
            }
        }
    }

    private EntityLivingBase findNearestTarget() {
        // Logic to find the nearest living entity
        return player.world.getNearestAttackablePlayer(player, 50.0, 50.0);
    }

    private void moveTowards(EntityLivingBase target) {
        // Logic to move towards the target entity linearly
        Vec3d playerPos = player.getPositionVector();
        Vec3d targetPos = target.getPositionVector();
        Vec3d direction = targetPos.subtract(playerPos).normalize();
        Vec3d newPos = playerPos.add(direction.scale(speed / 20.0)); // Move by speed per tick

        player.setPositionAndUpdate(newPos.x, newPos.y, newPos.z);
    }

    private void attack(EntityLivingBase target) {
        // Logic to attack the target entity
        target.attackEntityFrom(DamageSource.causePlayerDamage(player), 200.0f);
    }

    private void breakObstacles() {
        // Logic to break obstacles (blocks)
        BlockPos playerPos = player.getPosition();
        Vec3d lookVec = player.getLookVec();
        BlockPos blockPos = playerPos.add(lookVec.x, lookVec.y, lookVec.z); // Convert Vec3d to BlockPos

        if (!world.isAirBlock(blockPos)) {
            world.destroyBlock(blockPos, true);
        }
    }
}

处理程序

package daun.aut.utils.Handlers;

import daun.aut.utils.RageMode;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import org.lwjgl.input.Keyboard;

public class KeyInputHandler {

    private static final KeyBinding rageKey = new KeyBinding("key.ragemode", Keyboard.KEY_U, "key.categories.gameplay");

    public static void registerKeyBindings() {
        ClientRegistry.registerKeyBinding(rageKey);
    }

    @SubscribeEvent
    public void onKeyInput(InputEvent.KeyInputEvent event) {
        if (rageKey.isPressed()) {
            EntityPlayer player = Minecraft.getMinecraft().player;
            if (player != null) {
                new RageMode(player);
            }
        }
    }
}

我需要一切正常工作而不是崩溃。

java minecraft-forge
1个回答
0
投票

@ThomasKläger 的评论是正确的。输入事件在 Minecraft 的主线程上处理,因此阻塞输入处理程序将冻结游戏。在这种情况下,您的代码无限期地阻塞,导致游戏无限期地冻结。要了解原因,您必须了解

getTotalWorldTime
的工作原理。该方法返回的值仅在世界发生变化时才会增加。在阻塞主线程时,您可以防止世界滴答作响,防止
getTotalWorldTime
不断增加,防止您的代码退出该
while
循环,无限期地维持该块。

实现此功能的正确方法是将您的

RageMode
实例存储在播放器或其他地方,并在每次勾选时运行如下所示的内容(为此有一个 Forge 事件):

if (world.getTotalWorldTime() < startTime + duration) {
    EntityLivingBase target = findNearestTarget();
    if (target != null) {
        moveTowards(target);
        attack(target);
        breakObstacles();
    }
}

然后,当您点击

player.rageMode.startTime = player.world.getTotalWorldTime()
时,您可以执行
new RageMode(player)
或类似操作,而不是
rageKey

© www.soinside.com 2019 - 2024. All rights reserved.