zh_cn:tutorial:structures
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionLast revisionBoth sides next revision | ||
zh_cn:tutorial:structures [2021/07/24 16:22] – 拒绝机翻,从我做起! solidblock | zh_cn:tutorial:structures [2021/07/24 16:34] – [创建一个生成器] not done solidblock | ||
---|---|---|---|
Line 2: | Line 2: | ||
现在,往世界中注册并放置一些结构。 | 现在,往世界中注册并放置一些结构。 | ||
- | 入药查看原版结构的实例,可以从简单的'' | + | 入药查看原版结构的实例,可以从简单的'' |
对于大多数基本的结构,你需要地物(feature)和生成器(generator)。地物处理注册结构并在生成世界时加载的过程。生成器处理方块的放置,或者在结构文件中加载(如果选择这样做)。 | 对于大多数基本的结构,你需要地物(feature)和生成器(generator)。地物处理注册结构并在生成世界时加载的过程。生成器处理方块的放置,或者在结构文件中加载(如果选择这样做)。 | ||
Line 8: | Line 8: | ||
注意本教程依赖标记为实验性的[[https:// | 注意本教程依赖标记为实验性的[[https:// | ||
- | ==== 创建特征 | + | ===== 创建地物 |
+ | 要创建基本的地物(feature),我们推荐创建扩展'' | ||
- | 要创建基本功能,我们建议创建一个扩展AbstractTempleFeature < | + | 你需要覆写'' |
- | * shouldStartAt:出于测试目的,返回true。 | + | <code java> |
- | * getName:您的结构的名称 | + | public class MyFeature extends StructureFeature< |
- | * getRadius:结构的半径,用于放置 | + | |
- | * getSeeedModifier | + | super(codec); |
+ | } | ||
- | 您可以将DefaultFeatureConfig :: deserialize传递给构造函数进行测试。 | + | @Override |
+ | public StructureFeature.StructureStartFactory< | ||
+ | return Start::new; | ||
+ | } | ||
- | 对于getStructureStartFactory,大多数原始结构会创建一个在其Feature类中扩展StructureStart的类: | + | public static class Start extends |
+ | public Start(StructureFeature< | ||
+ | long seed) { | ||
+ | super(feature, | ||
+ | } | ||
- | <code java [enable_line_numbers=" | + | // 世界尝试在新的结构中生成时调用,同时也是地物和结构之间的“空隙(gap)”。 |
- | public static class MyStructureStart extends StructureStart { | + | public |
- | public | + | |
- | super(structureFeature_1, | + | int x = chunkX * 16; |
- | } | + | int z = chunkZ * 16; |
- | @Override | + | int y = chunkGenerator.getHeight(x, |
- | public void initialize(ChunkGenerator<?> | + | |
- | | + | |
- | | + | MyGenerator.addPieces(manager, pos, rotation, this.children); |
- | int z = chunkZ * 16; | + | this.setBoundingBoxFromChildren(); |
- | BlockPos | + | |
- | | + | |
- | MyGenerator.addParts(structureManager, startingPos, rotation, this.children, this.random, | + | |
- | this.setBoundingBoxFromChildren(); | + | |
} | } | ||
+ | } | ||
} | } | ||
</ | </ | ||
- | | ||
- | 当世界尝试以新结构生成时,这称为“要素”和“生成器”之间的差距。 在您的主类中对该变量的引用尚不存在,但我们将在最后创建它。 您也可以将配置设置为等于新的DefaultFeatureConfig。 您可以在getStructureStartFactory中使用返回MyStructureStart :: new返回此函数。 | ||
- | 这是结构文件和直接从generate方法生成的部分方式。 有两种解决方法: | ||
- | | + | ===== 创建生成器 |
- | | + | 你可能已经注意到,我们需要创建生成器。 |
- | ==== 创建一个生成器 ==== | + | This is where structure files and generating straight from a '' |
- | 您可能已经注意到,我们需要创建一个生成器。 我们将其命名为MyGenerator,并在StructureStart类的initialize方法中对其进行引用。 它不需要覆盖任何内容,但需要满足以下条件: | + | * If you want, you can simply override '' |
+ | * Use structure files. These are rather powerful at this point and are highly recommended. | ||
- | *指向您的结构文件的标识符; 如果需要示例,请使用'' | + | 本教程中,使用结构文件,不需要override任何内容,但确实需要: |
- | | + | |
+ | * 一些安装方法——例如'' | ||
<code java> | <code java> | ||
- | public static void addParts(StructureManager | + | public class MyGenerator { |
- | | + | private static final Identifier IGLOO_TOP = new Identifier(" |
- | + | ||
+ | | ||
+ | pieces.add(new MyPiece(manager, pos, IGLOO_TOP, rotation)); | ||
+ | } | ||
} | } | ||
</ | </ | ||
- | 在addParts方法中,您可以选择将哪些结构件添加到生成过程中。 | + | 在'' |
+ | |||
+ | 我们现在// | ||
+ | |||
+ | Override required methods, and add a constructor that takes in a '' | ||
+ | **toNbt isn't required but is available if you need it**. | ||
+ | We're also implementing '' | ||
+ | We also have 2 constructors: | ||
+ | A basic template would be: | ||
<code java> | <code java> | ||
- | list_1.add(new MyGenerator.Piece(structureManager_1, | + | public static class MyPiece extends SimpleStructurePiece { |
- | </ | + | private final BlockRotation rotation; |
+ | | ||
- | 标识符是我们最近创建的路径。 | + | public MyPiece(StructureManager structureManager, |
+ | super(ExampleMod.MY_PIECE, | ||
+ | this.template = new Identifier(compoundTag.getString(" | ||
+ | this.rotation = BlockRotation.valueOf(compoundTag.getString(" | ||
+ | this.initializeStructureData(structureManager); | ||
+ | } | ||
- | 现在,我们将创建我们刚刚引用的作品; 创建一个名为Piece的类,该类扩展了SimpleStructurePiece// | + | public MyPiece(StructureManager structureManager, |
+ | super(ExampleMod.MY_PIECE, 0); | ||
+ | this.pos = pos; | ||
+ | this.rotation = rotation; | ||
+ | this.template = template; | ||
- | 覆盖必需的方法,并添加一个接受StructureManager,Identifier,BlockPos和Rotation的构造函数。 ** toNbt不是必需的,但在需要时可用**。 我们还将使用不同的参数实现自己的setStructureData,因此它不是替代。 我们还有2个构造函数:1个构造函数,一个构造函数。 一个基本的模板是: | + | this.initializeStructureData(structureManager); |
- | <code java [enable_line_numbers=" | + | } |
- | public static class Piece extends SimpleStructurePiece { | + | |
- | private | + | private |
- | private Identifier template; | + | |
- | + | | |
- | public Piece(StructureManager | + | |
- | | + | .setMirror(BlockMirror.NONE) |
- | + | .addProcessor(BlockIgnoreStructureProcessor.IGNORE_STRUCTURE_BLOCKS); | |
- | this.pos | + | this.setStructureData(structure, this.pos, placementData); |
- | this.rotation = rotation_1; | + | } |
- | | + | |
- | + | protected void toNbt(CompoundTag | |
- | this.setStructureData(structureManager_1); | + | super.toNbt(tag); |
- | | + | tag.putString(" |
- | + | tag.putString(" | |
- | public Piece(StructureManager structureManager_1, | + | } |
- | super(MyModClass.myStructurePieceType, | + | |
- | this.identifier = new Identifier(compoundTag_1.getString(" | + | @Override |
- | this.rotation = Rotation.valueOf(compoundTag_1.getString(" | + | protected void handleMetadata(String |
- | this.setStructureData(structureManager_1); | + | |
- | } | + | } |
- | + | ||
- | | + | |
- | | + | |
- | super.toNbt(compoundTag_1); | + | |
- | | + | |
- | | + | |
- | } | + | |
- | + | ||
- | | + | |
- | Structure structure_1 = structureManager.getStructureOrBlank(this.identifier); | + | |
- | StructurePlacementData structurePlacementData_1 = (new StructurePlacementData()).setRotation(this.rotation).setMirrored(Mirror.NONE).setPosition(pos).addProcessor(BlockIgnoreStructureProcessor.IGNORE_STRUCTURE_BLOCKS); | + | |
- | this.setStructureData(structure_1, | + | |
- | } | + | |
- | + | ||
- | | + | |
- | protected void handleMetadata(String | + | |
- | + | ||
- | } | + | |
- | + | ||
- | @Override | + | |
- | public boolean generate(IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1, | + | |
- | + | ||
- | | + | |
} | } | ||
</ | </ | ||
| | ||
- | handleMetadata是查看结构中的数据块并根据发现的内容执行任务的地方。 在原版结构中,数据块放置在箱子上方,因此可以用这种方法将它们填满战利品。 | + | '' |
+ | This can be good for dynamic stuff such as placing certain mobs based on what mod is on and so on. | ||
- | 我们将StructurePieceType设置为MyModClass.myStructurePiece类型; 这是保存您注册的结构件的变量。 在完成generate函数之后,我们将对其进行处理,该函数将设置结构的位置并生成它: | + | In vanilla structures, data blocks are placed above chests so they can be filled with loot in this method. |
+ | HOWEVER, you do not need to use datablocks to place chests with loot. Instead, use this command to set a north facing chest with a loottable. | ||
+ | Save this chest into your structure' | ||
+ | < | ||
- | <code java [enable_line_numbers=" | + | We set the '' |
- | @Override | + | |
- | public boolean generate(IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1, | + | |
- | int yHeight = iWorld_1.getTop(Heightmap.Type.WORLD_SURFACE_WG, | + | |
- | | + | |
- | return super.generate(iWorld_1, | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | 在这种情况下,我们仅获取块中间最高块的y位置,并从该位置生成结构。 | + | |
==== 注册功能 ==== | ==== 注册功能 ==== |