我马上就说,在日志中没有出现错误,我在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);
}
}
}
}
我需要一切正常工作而不是崩溃。
@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
。