我的世界1.20.1forge模组开发(5)——自定义火球,HUD绘制

这期再来讲讲上一期没讲完的东西,怎么新建一个火球,这个火球和原版的火球不一样,他不会破坏方块,被点燃的实体不会停止燃烧,这就需要新建一个火球类继承原版的火球,冷却时间在下方显示,要绘制HUD然后动态显示冷却时间。

一、实体的定义 

在我的世界中,实体(entity)是游戏中可以互动的虚拟物体,如生物、怪物、玩家角色等。实体可以移动、进行攻击、被攻击、进行交互等操作。与实体不同,投掷物(projectile)是一种特殊的实体,通常是由玩家或某些生物投掷出去的物体,如箭矢、火球等。

在我的世界中,实体分为多种类型,包括但不限于:

  1. 生物类实体:如动物、怪物以及玩家本身都属于生物类实体,它们可以移动、进行攻击等操作。

  2. 物品实体:如掉落的物品、放置的物品等,可以被玩家拾取或进行交互。

  3. 方块实体:如推动的方块、活塞推出的方块等,也属于实体的一种。

总的来说,在我的世界中,实体是游戏中重要的元素之一,玩家与实体的互动和操作是游戏的核心内容之一。

二、新建实体

在 Minecraft 1.20.1 Forge 模组开发中,创建一个新的实体涉及多个步骤。

首先需要定义一个继承自 `Entity` 类的新实体类。

public class ExampleEntity extends Entity {
    private static final EntityDataAccessor<Integer> DATA_EXAMPLE_VALUE = SynchedEntityData.defineId(ExampleEntity.class, EntityDataSerializers.INT);

    public ExampleEntity(EntityType<?> type, Level world) {
        super(type, world);
    }

    @Override
    protected void defineSynchedData() {
        this.entityData.define(DATA_EXAMPLE_VALUE, 0);
    }

    @Override
    protected void readAdditionalSaveData(CompoundTag compoundTag) {
        this.entityData.set(DATA_EXAMPLE_VALUE, compoundTag.getInt("ExampleValue"));
    }

    @Override
    protected void addAdditionalSaveData(CompoundTag compoundTag) {
        compoundTag.putInt("ExampleValue", this.entityData.get(DATA_EXAMPLE_VALUE));
    }
}

代码功能总结:

这段代码定义了一个名为ExampleEntity的类,这个类继承自Minecraft中的Entity类。它主要用于在Minecraft中创建一个自定义实体,并实现了同步数据和保存/加载额外数据的功能。下面是对代码的详细分解:

  1. 类定义和继承

    public class ExampleEntity extends Entity {
    
    • ExampleEntity类继承了Entity类,意味着它是一个实体对象,可以存在于Minecraft的世界中。
    • public关键字表示这个类可以被其他类访问。
  2. 定义同步数据

    private static final EntityDataAccessor<Integer> DATA_EXAMPLE_VALUE = SynchedEntityData.defineId(ExampleEntity.class, EntityDataSerializers.INT);
    
    • EntityDataAccessor<Integer>是一个泛型接口,用于访问实体的同步数据。
    • DATA_EXAMPLE_VALUE是一个静态常量,用于存储这个实体的一个整型同步变量。
    • SynchedEntityData.defineId方法用于为实体定义一个唯一标识符,这个标识符用于在网络中同步数据。
    • EntityDataSerializers.INT指定这个同步变量的数据类型为整型。
  3. 构造方法

    public ExampleEntity(EntityType<?> type, Level world) {
        super(type, world);
    }
    
    • 构造方法用于创建ExampleEntity对象。
    • EntityType<?> type表示该实体的类型,Level world表示该实体所在的Minecraft世界。
    • super(type, world)调用了父类Entity的构造方法,初始化了实体的基本属性。
  4. 定义同步数据值

    @Override
    protected void defineSynchedData() {
        this.entityData.define(DATA_EXAMPLE_VALUE, 0);
    }
    
    • 重写了defineSynchedData()方法,用于定义实体的同步数据。
    • this.entityData.define(DATA_EXAMPLE_VALUE, 0)使用之前定义的DATA_EXAMPLE_VALUE标识符,将一个初始值为0的整型数据添加到entityData中。entityData是一个SynchedEntityData对象,用于管理实体的同步数据。
  5. 读取附加保存数据

    @Override
    protected void readAdditionalSaveData(CompoundTag compoundTag) {
        this.entityData.set(DATA_EXAMPLE_VALUE, compoundTag.getInt("ExampleValue"));
    }
    
    • 重写了readAdditionalSaveData()方法,用于从CompoundTag对象中读取实体的额外保存数据。
    • CompoundTag是一种数据结构,可以存储多种类型的数据,这里用于存储实体的状态信息。
    • compoundTag.getInt("ExampleValue")CompoundTag中读取名为ExampleValue的整数值,并将其设置到实体的同步数据中。
  6. 添加附加保存数据

    @Override
    protected void addAdditionalSaveData(CompoundTag compoundTag) {
        compoundTag.putInt("ExampleValue", this.entityData.get(DATA_EXAMPLE_VALUE));
    }
    
    • 重写了addAdditionalSaveData()方法,用于将实体的额外数据保存到CompoundTag对象中。
    • this.entityData.get(DATA_EXAMPLE_VALUE)从实体的同步数据中获取DATA_EXAMPLE_VALUE的值。
    • compoundTag.putInt("ExampleValue", ...)将获取到的值保存到CompoundTag对象中,键名为ExampleValue
总结

这段代码的主要功能是定义一个自定义的Minecraft实体ExampleEntity,并实现了一个整型同步变量DATA_EXAMPLE_VALUE的同步和保存/加载功能。同步功能使得客户端和服务器上的实体数据保持一致,而保存/加载功能允许实体的状态在游戏存档中持久化。

注册实体到事件总线中

    private static final DeferredRegister<EntityType<?>> ENTITY_TYPES = DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, "example_mod");

    public static final RegistryObject<EntityType<ExampleEntity>> EXAMPLE_ENTITY = ENTITY_TYPES.register("example_entity", () ->
            EntityType.Builder.<ExampleEntity>of(ExampleEntity::new, MobCategory.MISC)
                    .sized(0.6F, 1.8F).clientTrackingRange(8).updateInterval(3).build(new ResourceLocation("example_mod:example_entity").toString()));

    public static void init() {
        IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
        ENTITY_TYPES.register(modEventBus);
    }

这段代码是Minecraft Forge模组开发中用于注册自定义实体类型的一部分。下面是对这段代码的逐步分解和详细解释:

  1. 实体类型注册器的创建:

    private static final DeferredRegister<EntityType<?>> ENTITY_TYPES = DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, "example_mod");
    

    这行代码创建了一个DeferredRegister对象,专门用于注册实体类型。DeferredRegister是Forge提供的一个类,允许在游戏生命周期的适当阶段(如数据加载阶段)注册内容,而不是在构造函数中立即注册。ForgeRegistries.ENTITY_TYPES表示要注册的是实体类型,而"example_mod"是模组的ID。

  2. 注册自定义实体类型:

    public static final RegistryObject<EntityType<ExampleEntity>> EXAMPLE_ENTITY = ENTITY_TYPES.register("example_entity", () ->
            EntityType.Builder.<ExampleEntity>of(ExampleEntity::new, MobCategory.MISC)
                    .sized(0.6F, 1.8F).clientTrackingRange(8).updateInterval(3).build(new ResourceLocation("example_mod:example_entity").toString()));
    

    这段代码通过DeferredRegisterregister方法注册了一个自定义实体类型ExampleEntityRegistryObject<EntityType<ExampleEntity>>是一个引用对象,它将在实体类型实际注册后引用该实体类型。EntityType.Builder用于构建实体类型实例,其中ExampleEntity::new是一个构造函数引用,表示如何实例化实体。MobCategory.MISC表示该实体的分类,这里使用的是“杂项”分类。sized(0.6F, 1.8F)设置了实体的大小,宽度为0.6,高度为1.8。clientTrackingRange(8)定义了客户端跟踪此实体的最大距离为8个方块。updateInterval(3)定义了客户端和服务器之间同步实体状态的频率,这里每3个游戏刻同步一次。最后,build(new ResourceLocation("example_mod:example_entity").toString())构建了实体类型,并使用ResourceLocation来唯一标识该实体类型。

  3. 初始化实体注册:

    public static void init() {
        IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
        ENTITY_TYPES.register(modEventBus);
    }
    

    init方法用于将之前创建的实体类型注册器ENTITY_TYPES与模组的事件总线modEventBus关联起来。FMLJavaModLoadingContext.get().getModEventBus()获取了模组的事件总线,然后通过ENTITY_TYPES.register(modEventBus)在模组加载时注册所有通过ENTITY_TYPES注册的实体类型。

总结:

 这段代码的主要功能是创建并注册一个名为ExampleEntity的自定义实体类型。通过使用DeferredRegister,确保了实体类型在正确的生命周期阶段被注册。此外,还设置了该实体的基本属性,如大小、跟踪范围和更新频率,并为其实体类型创建了一个ResourceLocation,以确保它是唯一且可以被Minecraft识别的。

三、EntityRenderersEvent事件

EntityRenderersEvent 是 Forge 模组开发框架中用于处理实体渲染器注册的事件类,它属于 Forge 事件总线系统的一部分。在 Minecraft 模组开发里,当你需要为自定义实体指定渲染器时,就可以借助 EntityRenderersEvent 来达成这一目的。
EntityRenderersEvent 的用途
EntityRenderersEvent 有多个子类,每个子类对应不同的渲染器注册阶段,不过最常用的是 EntityRenderersEvent.RegisterRenderers。这个子类事件允许你在模组初始化期间注册自定义实体的渲染器。
如何使用 EntityRenderersEvent 渲染实体
步骤 1:定义自定义实体
首先,你得定义一个自定义实体类,并且在 EntityRegistry 里注册这个实体。
步骤 2:创建实体渲染器
接着,你需要创建一个渲染器类,这个类要继承自合适的渲染器基类,例如 ThrownItemRen

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lemon_sjdk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值