User Tools

Site Tools


zh_cn:tutorial:structures

生成结构

特征

本教程中使用的所有代码都可以在此处获得: fabric-structure-example-repo

介绍

我们将研究如何在您的世界中注册和放置结构。

要查看实际使用的1.14原版结构的示例,IglooGenerator和IglooFeature是一个良好的开端。

对于最基本的结构,您将需要一个功能部件和生成器。 该功能处理在生成世界时注册结构并将其加载的过程-回答诸如“我应该在这里生成吗?”和‘我叫什么名字?’之类的问题,生成器处理块的放置或加载 结构文件(如果您选择这样做)。

创建特征

要创建基本功能,我们建议创建一个扩展AbstractTempleFeature <DefaultFeatureConfig>的类。 海难,雪屋和神殿等各种原版结构都使用AbstractTempleFeature作为基础。 您将必须重写以下方法:

  • shouldStartAt:出于测试目的,返回true。
  • getName:您的结构的名称
  • getRadius:结构的半径,用于放置
  • getSeeedModifier

您可以将DefaultFeatureConfig :: deserialize传递给构造函数进行测试。

对于getStructureStartFactory,大多数原始结构会创建一个在其Feature类中扩展StructureStart的类:

  1. public static class MyStructureStart extends StructureStart {
  2. public MyStructureStart (StructureFeature<?> structureFeature_1, int int_1, int int_2, Biome biome_1, MutableIntBoundingBox mutableIntBoundingBox_1, int int_3, long long_1) {
  3. super(structureFeature_1, int_1, int_2, biome_1, mutableIntBoundingBox_1, int_3, long_1);
  4. }
  5. @Override
  6. public void initialize(ChunkGenerator<?> chunkGenerator, StructureManager structureManager, int chunkX, int chunkZ, Biome biome) {
  7. DefaultFeatureConfig defaultFeatureConfig = chunkGenerator.getStructureConfig(biome, MyMainclass.myFeature);
  8. int x = chunkX * 16;
  9. int z = chunkZ * 16;
  10. BlockPos startingPos = new BlockPos(x, 0, z);
  11. Rotation rotation = Rotation.values()[this.random.nextInt(Rotation.values().length)];
  12. MyGenerator.addParts(structureManager, startingPos, rotation, this.children, this.random, defaultFeatureConfig);
  13. this.setBoundingBoxFromChildren();
  14. }
  15. }

当世界尝试以新结构生成时,这称为“要素”和“生成器”之间的差距。 在您的主类中对该变量的引用尚不存在,但我们将在最后创建它。 您也可以将配置设置为等于新的DefaultFeatureConfig。 您可以在getStructureStartFactory中使用返回MyStructureStart :: new返回此函数。 这是结构文件和直接从generate方法生成的部分方式。 有两种解决方法:

  • 如果需要,您可以简单地在Feature类中重写generate,并使用setBlockState将块直接放置在世界上。 这是一个有效的选项,在1.13之前很流行。
  • 使用结构文件和生成器。 在这一点上,这些功能非常强大,因此强烈建议使用。

创建一个生成器

您可能已经注意到,我们需要创建一个生成器。 我们将其命名为MyGenerator,并在StructureStart类的initialize方法中对其进行引用。 它不需要覆盖任何内容,但需要满足以下条件:

*指向您的结构文件的标识符; 如果需要示例,请使用igloo / top

  • 某种安装方法-addParts是一个好名字:
public static void addParts(StructureManager structureManager_1, BlockPos blockPos_1, Rotation rotation_1, 
    List<StructurePiece> list_1, Random random_1, DefaultFeatureConfig featureConfig)
 
}

在addParts方法中,您可以选择将哪些结构件添加到生成过程中。 您可以添加如下内容:

list_1.add(new MyGenerator.Piece(structureManager_1, identifier, blockPos, rotation_1));

标识符是我们最近创建的路径。

现在,我们将创建我们刚刚引用的作品; 创建一个名为Piece的类,该类扩展了SimpleStructurePiece在您的生成器类中.

覆盖必需的方法,并添加一个接受StructureManager,Identifier,BlockPos和Rotation的构造函数。 toNbt不是必需的,但在需要时可用。 我们还将使用不同的参数实现自己的setStructureData,因此它不是替代。 我们还有2个构造函数:1个构造函数,一个构造函数。 一个基本的模板是:

  1. public static class Piece extends SimpleStructurePiece {
  2. private Rotation rotation;
  3. private Identifier template;
  4.  
  5. public Piece(StructureManager structureManager_1, Identifier identifier_1, BlockPos blockPos_1, Rotation rotation_1) {
  6. super(MyModClass.myStructurePieceType, 0);
  7.  
  8. this.pos = blockPos_1;
  9. this.rotation = rotation_1;
  10. this.template = identifier_1;
  11.  
  12. this.setStructureData(structureManager_1);
  13. }
  14.  
  15. public Piece(StructureManager structureManager_1, CompoundTag compoundTag_1) {
  16. super(MyModClass.myStructurePieceType, compoundTag_1);
  17. this.identifier = new Identifier(compoundTag_1.getString("Template"));
  18. this.rotation = Rotation.valueOf(compoundTag_1.getString("Rot"));
  19. this.setStructureData(structureManager_1);
  20. }
  21.  
  22. @Override
  23. protected void toNbt(CompoundTag compoundTag_1) {
  24. super.toNbt(compoundTag_1);
  25. compoundTag_1.putString("Template", this.template.toString());
  26. compoundTag_1.putString("Rot", this.rotation.name());
  27. }
  28.  
  29. public void setStructureData(StructureManager structureManager) {
  30. Structure structure_1 = structureManager.getStructureOrBlank(this.identifier);
  31. StructurePlacementData structurePlacementData_1 = (new StructurePlacementData()).setRotation(this.rotation).setMirrored(Mirror.NONE).setPosition(pos).addProcessor(BlockIgnoreStructureProcessor.IGNORE_STRUCTURE_BLOCKS);
  32. this.setStructureData(structure_1, this.pos, structurePlacementData_1);
  33. }
  34.  
  35. @Override
  36. protected void handleMetadata(String string_1, BlockPos blockPos_1, IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1) {
  37.  
  38. }
  39.  
  40. @Override
  41. public boolean generate(IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1, ChunkPos chunkPos_1) {
  42.  
  43. }
  44. }

handleMetadata是查看结构中的数据块并根据发现的内容执行任务的地方。 在原版结构中,数据块放置在箱子上方,因此可以用这种方法将它们填满战利品。

我们将StructurePieceType设置为MyModClass.myStructurePiece类型; 这是保存您注册的结构件的变量。 在完成generate函数之后,我们将对其进行处理,该函数将设置结构的位置并生成它:

  1. @Override
  2. public boolean generate(IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1, ChunkPos chunkPos_1) {
  3. int yHeight = iWorld_1.getTop(Heightmap.Type.WORLD_SURFACE_WG, this.pos.getX() + 8, this.pos.getZ() + 8);
  4. this.pos = this.pos.add(0, yHeight - 1, 0);
  5. return super.generate(iWorld_1, random_1, mutableIntBoundingBox_1, chunkPos_1);
  6. }

在这种情况下,我们仅获取块中间最高块的y位置,并从该位置生成结构。

注册功能

最后一步是注册我们的功能。 我们需要注册:

  • StructurePieceType
  • StructureFeature<DefaultFeatureConfig>
  • StructureFeature<?>

我们还需要将结构添加到“结构”列表中,并将其添加到每个生物群系中,作为功能部件和生成步骤。

注册件类型:

public static final StructurePieceType myStructurePieceType = Registry.register(Registry.STRUCTURE_PIECE, "my_piece", MyGenerator.Piece::new);

注册功能:

public static final StructureFeature<DefaultFeatureConfig> myFeature = Registry.register(Registry.FEATURE, "my_feature", new MyFeature());

注册结构:

public static final StructureFeature<?> myStructure = Registry.register(Registry.STRUCTURE_FEATURE, "my_structure", myFeature);

要将功能放入功能列表,可以使用:

Feature.STRUCTURES.put("My Awesome Feature", myFeature);

对于测试,将功能注册到每个生物群系并将生成率设置为100%是个好主意,这样您就可以确保其生成并正常工作。 您可能不希望您的结构漂浮在水中,因此我们也将其过滤掉。 通过遍历生物群系列表并将其添加为特征和生成步骤,将其添加到每个生物群系:

  1. for(Biome biome : Registry.BIOME) {
  2. if(biome.getCategory() != Biome.Category.OCEAN && biome.getCategory() != Biome.Category.RIVER) {
  3. biome.addStructureFeature(myFeature, new DefaultFeatureConfig());
  4. biome.addFeature(GenerationStep.Feature.SURFACE_STRUCTURES, Biome.configureFeature(myFeature, new DefaultFeatureConfig(), Decorator.CHANCE_PASSTHROUGH, new ChanceDecoratorConfig(0)));
  5. }
  6. }

ChanceDecoratorConfig的参数基本上是在生成之前将跳过多少个块。 0是每个块,1是彼此,并且100是每100。

您需要将结构添加为特征,以便您的生物群系知道其存在,然后作为生成步骤,以使其实际生成。

加载到您的世界中,如果一切顺利,应该会遇到很多的雪屋。

zh_cn/tutorial/structures.txt · Last modified: 2020/02/04 10:59 by lightcolour