minecraft forge - 我如何获得一个实体并改变它的状态?

minecraft forge - How would I get a entity and change it's state?

我从锻造模组开始,我想让所有苦力怕都生成为带电苦力怕。我正在使用 forge MDK 1.16.3.

这是我的事件处理程序:

package com.modder.mod.events;

import net.minecraft.entity.Entity;
import net.minecraftforge.event.entity.living.LivingSpawnEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;

public class EventHandler 
{
    @SubscribeEvent
    public static void mobEvent(LivingSpawnEvent event)
    {
        Entity entity;
        
        
    }
}

但我不知道这之后要做什么。提前致谢!

每次在世界中生成一个实体时,LivingSpawnEvent 都会触发,这包括当您离开然后 return 时,请记住这一点。

由于每个生成的实体都会触发该事件,我们想检查该实体是否是苦力怕,因此我们检查它是否是 CreeperEntity class 和 return 的实例如果不是。

if(!(event.getEntity() instanceof CreeperEntity))
    return;

现在我们知道我们有一个苦力怕,我们可以安全地施放它来获得苦力怕实体。然后我们检查苦力怕是否已经充电,如果是 return;因为没有必要继续了。

CreeperEntity creeper = (CreeperEntity) event.getEntity();
if(creeper.isCharged())
    return;

通常情况下,爬行者会因雷击而充电,我们可以模拟此功能使爬行者充电:

LightningBoltEntity lightningBoltEntity = new LightningBoltEntity(event.getWorld().getWorld(), event.getX(), event.getY(), event.getZ(), true);
((ServerWorld) event.getWorld()).addLightningBolt(lightningBoltEntity);
creeper.onStruckByLightning(lightningBoltEntity);

这次打击会伤害苦力怕。

但是,如果我们不想要雷击,我们必须更改 POWERED 数据管理器布尔值。该字段是私有的,但我们可以使用 reflection.

首先,我们定义一个新的 Field 然后尝试获取 POWERED 字段并将其设置为可访问。

Field field;
field = creeper.getClass().getDeclaredField("POWERED");
field.setAccessible(true);

然后我们可以将值设置为 true,这将使苦力怕充电。

DataParameter<Boolean> powered = (DataParameter<Boolean>) field.get(creeper);
creeper.getDataManager().set(powered, true);

最后,我们应该将其包装在 try/catch 中,因为我们无法控制 CreeperEntity 的内容,因此我们无法保证我们对其内容的假设在执行时是准确的,所以我们定义了我们将如何处理错误。在这种情况下,出于演示目的,我忽略了任何预期的异常。

@SubscribeEvent
public void autoChargeCreeper(LivingSpawnEvent event)
{
    if(!(event.getEntity() instanceof CreeperEntity))
        return;
    CreeperEntity creeper = (CreeperEntity) event.getEntity();
    if(creeper.isCharged())
        return;
    try
    {
        Field field;
        field = creeper.getClass().getDeclaredField("POWERED");
        field.setAccessible(true);
        DataParameter<Boolean> powered = (DataParameter<Boolean>) field.get(creeper);
        creeper.getDataManager().set(powered, true);
    } catch (NoSuchFieldException | IllegalAccessException ignored) { }
}