NeoForge开发文档-第二章第一节 创建简单方块

第四章、总序     方块

  方块对于Minecraft的世界来说是至关重要的,它们构成了所有的地形、结构以及机器。如果您想制作一个模组,那么您可能会想要创建一些方块。本页将指导您通过创建一些方块来告诉您可以用它们做什么事情。

One Block to Rule Them All

一个方块统治所有方块

  在我们开始之前,理解每一个方块在游戏里只有一个是非常重要的。一个世界是由成千上万个同一个方块在不同的地方的引用组成的。换言之,就是同一个方块同时出现了很多次。

        因此,一个方块应该只在注册(https://docs.neoforged.net/docs/concepts/registries/#methods-for-registering)的时候被实例化一次。一旦这个方块被注册了,你就可以在需要的时候引用这个被注册的方块。

        不像其它大多数的注册,方块可以使用的一个专用的DeferredRegister版本,它就是DeferredRegister.BlocksDeferredRegister.Blocks基本上和DeferredRegister<Block>差不多,但也有一些小区别。

  • 它们被通过DeferredRegister.createBlocks(“yourmoid”) 创建,而非常见的DeferredRegister.create(…)方法。

  • #register返回的是一个继承了DeferredHolder<Block,  T>的DeferredBlock<T extends Block>。T是我们正在注册的方块的Java类的类别。

  •      有一些创建方块的辅助方法,详情请参阅下文。

        所以现在,让我们一起注册我们的方块吧:

        //BLOCKS 是一个 DeferredRegister.Blocks。(这里我们还没有演示创建它,所以如果您此刻正在使用您的IDE做同样的事情,那么它应该会报错。这不要紧,下面我们将会解决这个问题。)

        public static final DeferredBlock<Block> MY_BLOCK = BLOCKS.register(“my_block”,

()->new Block(…));

        在注册了方块之后,所有新的对my_block的引用都应该使用这个常量。例如,如果你想检查给定位置的方块是否是my_block,那么这段代码应该看起来象是这样:

        level.getBlockState(position)//返回在给定的世界中给定的位置被放置的方块的方块状态。

         .is(MyBlockRegistrationClass.MY_BLOCK.get());

        这个方法还有一个便利的效果,也就是使用block 1 == block2 是有效的,可以用来代替Java中的equals方法(当然,equals仍然是可以使用的,但那是毫无意义的,因为无论如何,它都是通过引用来进行比较的。

警告!

        不要在注册流程之外调用new Block() !一旦你这么做了,事情将会变得很糟糕。

  • 方块必须在注册表未被冻结之前创建。NeoForge将会在合适的时候为您短暂的解冻注册表并在之后重新冻结注册表。所以注册期间也是您创建方块的时间。

  • 如果您尝试在注册表再一次被冻结之后去创建或者注册一个方块,游戏将会崩溃并报告一个空的方块,这可能会让人感到十分困惑。

  • 如果您仍然设法获得了一个悬空方块示例,游戏将无法在同步和保存时识别出该方块并将其替换为空气。

Creating Blocks

创建方块

  就像前面所说的那样,我们首先需要创建我们的DeferredRegister.Blocks:

            public static final DeferredRegister.Blocks BLOCK = DeferredRegister.createBlocks(“yourmodid)”;

Basic Blocks

基础方块

  对于一个不需要特殊功能的简单方块(就像圆石,木板等等)来说,可以直接使用Block类。为此,需要在注册时使用BlockBehaviour.Properties参数实例化Block。BlockBehaviour.Properties参数可以使用BlockBehaviourProperties#of方法来创建,也可以使用它的方法来自定义。这是一些很重要的方法:

  • destroyTime – 方块被破坏时需要的时间。

    • 石头的破坏时间是1.5,泥土的是0.5,黑曜石的是50,而基岩的是-1(不可被破坏)。

  • explosionResistance      – 方块的防爆能力

    • 石头的防爆能力是6.0,泥土的是0.5,黑曜石的是1200,而基岩的是3600000。

  • sound –  设置方块在被敲打(踩踏)、破坏或者放置时的声音。

    • 默认值是SoundType.STONE,更多详细信息可以查看声音页。

  • lightLevel–      设置方块发出的光亮。接受一个返回值在0-15之间的BlockState参数。

    • 例如,萤石使用state->15,而火把则是state->14。

  • friction– 设置方块的光滑程度。

    • 默认值是0.6,冰块是0.98。

        举个例子, 一个简单的实现应该看起来像这样:

                //BLOCKS is a DeferredRegister.Blocks

public static final DeferredBlock<Block> MY_BETTER_BLOCK = BLOCKS.register(

         “my_better_block”,

        () -> new Block(BlockBehaviour.Properties.of()

                .destroyTime(2.0f)

                .explosionResistance(10.0f)

                .sound(SoundType.GRAVEL)

                .lightLevel(state -> 7)

));

 

可以参阅BlockBehaviour.Properties的源代码文档来获取更多信息,也可以查看Minecraft中Blocks类来获取更多的例子。

 

i提醒

理解在世界中的方块和在物品栏的方块不是同一个东西是很重要的。在物品栏中看起来很像方块的物品实际上是一个BlockItem,它是一种被使用时会放置一个方块的特殊Item。

一个BlockItem必须和Block分开注册。这是因为Block不一定需要一个BlockItem,例如如果它不能被收集(比如火就是这种情况)。

这也意味着像创造物品栏或者最大堆叠数量等属性都是对相应的BlockItem的设置。

More Functionality

更多的功能

  直接使用Block只能创建一个非常基础的方块。如果您想添加更多的功能,比如玩家交互或者一个与众不同的碰撞体积,您需要一个继承自Block的自定义类。Block类有需多可以重载的方法用来做各种不同的事情;查看Block、BlockBehaviour和IBlockExtension类来获取更多的信息。也可以通过查看下面的Using blocks(待施工)的部分来了解一下很常见的blocks的实例。

      如果您想制作一个有不同变体的方块(例如一个有顶部、底部和两个都存在的台阶变体),您应该使用blockstates(待施工)。最后,如果您想让一个方块可以存储一些额外的数据(想想一个存储物品的箱子),您应该去使用block entity(待施工)。这里有一条经验法则,如果您的方块只有数量有限且不多的状态(最多几百个状态),使用blockstates,如果您的方块拥有无限或接近无限个状态,则使用block entity。

 

DeferredRegister.Blocks helpers

DeferredRegister.Blocks助手

  我们在上面已经讨论了如何去创建一个DeferredRegister.Blocks以及他返回的DeferredBlock。现在,让我们一起来看看专门DeferredRegister还提供了哪些使用的程序。让我们通过#registerBlock开始吧:

        public static final DeferredRegister.Blocks BLOCKS =         DeferredRegister.createBlocks(“yourmodid”);

        public static final DeferredBlock<Block> EXAMPLE_BLOCK = BLOCKS.registerBlock(

                “example”,

                BLOCK::new,

                BlockBehaviour.Properties.of()

        );

 

        在内部,这将通过使用properties参数来提供一个方块工厂(通常是一个构造函数),以简单地调用BLOCKS.register(“example_block”, ()-> new Block(BlockBehaviour.Properties.of()))

 

        如果您想使用Block::new,您可以完全地省略工厂:

                public static final DeferredBlock<Block> EXAMPLE_BLOCK =         BLOCKS.registerSimpleBlock(

                        “example_block”,

                        “BlockBehaviour.Properties.of()

                );

 

        这和之前的示例一模一样,但是比起来更短一些。当然,如果您想使用Block的子类而不是Block本身,您将不得不使用之前的方法。

 

Resources

资源

  如果您现在将您注册的方块放置在世界上,您将会发现它缺少了纹理之类的东西。这是因为纹理等内容是用Minecraft的资源系统处理的。

        为了给一个方块应用一个简单的纹理,您必须添加一个方块状态(blockstate)的JSON文件以及一个模型(model)的 JSON文件以及一个纹理的PNG文件。可以在resources(待施工)的部分查阅更多的信息。

资源下载: