User Tools

Site Tools


zh_cn:tutorial:structures

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
zh_cn:tutorial:structures [2021/07/24 16:23] solidblockzh_cn:tutorial:structures [2021/07/24 16:34] – [创建一个生成器] not done solidblock
Line 8: Line 8:
 注意本教程依赖标记为实验性的[[https://github.com/FabricMC/fabric/pull/1097|Fabric API中的生物群系修改API]]。如果API不起作用,考虑使用[[?rev=1599808070|mixin版本]]。 注意本教程依赖标记为实验性的[[https://github.com/FabricMC/fabric/pull/1097|Fabric API中的生物群系修改API]]。如果API不起作用,考虑使用[[?rev=1599808070|mixin版本]]。
  
-==== 创建特征 ====+===== 创建地物 ====
 +要创建基本的地物(feature),我们推荐创建扩展''StructureFeature<DefaultFeatureConfig>''的类。大多数原版结构,如沉船、雪屋、神殿都是以''StructureFeature<DefaultFeatureConfig>''为基础,
  
-创建基本功能我们建议创建一个扩展AbstractTempleFeature <DefaultFeatureConfig>的类。 海难,雪屋和神殿等各种原版结构都使用AbstractTempleFeature作为基础。 您将必须重写以下方法:+你需覆写''getStructureStartFactory''方法。对于''getStructureStartFactory''大多数原版的结构在其地物类中创建扩展''StructureStart''的类。
  
-   * shouldStartAt:出于测试目的,返回true。 +<code java> 
-   * getName:您的结构的名称 +public class MyFeature extends StructureFeature<DefaultFeatureConfig> { 
-   * getRadius:结构的半径,用于放置 +  public MyFeature(Codec<DefaultFeatureConfig> codec) { 
-   * getSeeedModifier+    super(codec); 
 +  }
  
-您可以将DefaultFeatureConfig :: deserialize传递给构造函数进行测试。+  @Override 
 +  public StructureFeature.StructureStartFactory<DefaultFeatureConfig> getStructureStartFactory() { 
 +    return Start::new; 
 +  }
  
-对于getStructureStartFactory,大多数原始结构会创建一个在其Feature类中扩展StructureStart的类:+  public static class Start extends StructureStart<DefaultFeatureConfig>
 +    public Start(StructureFeature<DefaultFeatureConfig> feature, int chunkX, int chunkZ, BlockBox box, int references, 
 +        long seed) { 
 +      super(feature, chunkX, chunkZ, box, references, seed); 
 +    }
  
-<code java [enable_line_numbers="true"]> +    // 世界尝试在新的结构中生成时调用,同时也是地物和结构之间的“空隙(gap)”。 
-public static class MyStructureStart extends StructureStart { +    public void init(DynamicRegistryManager registryManager, ChunkGenerator chunkGenerator, StructureManager manager, int chunkX, 
-    public MyStructureStart (StructureFeature<?> structureFeature_1int int_1, int int_2, Biome biome_1, MutableIntBoundingBox mutableIntBoundingBox_1, int int_3, long long_1) { +        int chunkZ, Biome biome, DefaultFeatureConfig config) { 
-        super(structureFeature_1, int_1, int_2, biome_1, mutableIntBoundingBox_1, int_3, long_1); +      int x = chunkX * 16; 
-    } +      int z = chunkZ * 16; 
-    @Override +      int y = chunkGenerator.getHeight(x, z, Heightmap.Type.WORLD_SURFACE_WG); 
-    public void initialize(ChunkGenerator<?> chunkGenerator, StructureManager structureManager, int chunkX, int chunkZ, Biome biome) { +      BlockPos pos = new BlockPos(x, y, z); 
-        DefaultFeatureConfig defaultFeatureConfig = chunkGenerator.getStructureConfig(biome, MyMainclass.myFeature); +      BlockRotation rotation = BlockRotation.random(this.random); 
-        int x = chunkX * 16; +      MyGenerator.addPieces(managerpos, rotation, this.children); 
-        int z = chunkZ * 16; +      this.setBoundingBoxFromChildren();
-        BlockPos startingPos = new BlockPos(x, 0, z); +
-        Rotation rotation = Rotation.values()[this.random.nextInt(Rotation.values().length)]+
-        MyGenerator.addParts(structureManagerstartingPos, rotation, this.children, this.random, defaultFeatureConfig); +
-        this.setBoundingBoxFromChildren();+
     }     }
 +  }
 } }
 </code> </code>
-     
-当世界尝试以新结构生成时,这称为“要素”和“生成器”之间的差距。 在您的主类中对该变量的引用尚不存在,但我们将在最后创建它。 您也可以将配置设置为等于新的DefaultFeatureConfig。 您可以在getStructureStartFactory中使用返回MyStructureStart :: new返回此函数。 
-这是结构文件和直接从generate方法生成的部分方式。 有两种解决方法: 
  
-   *如果需要,您可以简单地在Feature类中重写generate,并使用setBlockState将块直接放置在世界上。 这是一个有效的选项,在1.13之前很流行。 +===== 创建生成器 ===== 
-   *使用结构文件和生成器。 在这一点上,这些功非常强大因此强烈议使用+你可已经注意到我们需要创生成器
  
-==== 创建一个生成器 ====+This is where structure files and generating straight from a ''generate'' method part ways. 有两种方式实现这样做:
  
-您可能已经注意到,我们需要创建一个生成器。 我们将其命名为MyGenerator,并在StructureStart类的initialize方法中对其进行引用。 它不需要覆盖任何内容,但需要满足以下条件:+  * If you want, you can simply override ''generate'' in your piece class and use ''addBlock'' to place blocks directly in the world. This is a valid option and was popular pre-1.13. 
 +  * Use structure files. These are rather powerful at this point and are highly recommended.
  
-*指向您的结构文件的标识符; 如果需要示例请使用''igloo / top''。 +本教程中,使用结构文件,不需要override任何内容,但确实需要: 
-   *某种安装方法-addParts是一个好名字:+  * 指向结构文件的标识符(identifier例如''"igloo/top"''。 
 +  一些安装方法——例如''addPieces''就很不错。
  
 <code java> <code java>
-public static void addParts(StructureManager structureManager_1, BlockPos blockPos_1Rotation rotation_1 +public class MyGenerator { 
-    List<StructurePiece> list_1Random random_1DefaultFeatureConfig featureConfig+  private static final Identifier IGLOO_TOP = new Identifier("igloo/top"); 
-    + 
 +  public static void addPieces(StructureManager manager, BlockPos posBlockRotation rotation, List<StructurePiece> pieces) { 
 +    pieces.add(new MyPiece(managerposIGLOO_TOP, rotation)); 
 +  }
 } }
 </code> </code>
  
-addParts方法中,可以选择哪些结构件添加到生成过程中。 您可以添加如下内容:+''addPieces''方法中,可以选择往你的生成过程中添加哪些结构。 
 + 
 +我们现在//生成器类//创建我们刚刚提到的结构,创建名为''MyPiece''的类,继承''SimpleStructurePiece'' 
 + 
 +Override required methods, and add a constructor that takes in a ''StructureManager'', ''BlockPos'', ''Identifier'' and ''Rotation''
 +**toNbt isn't required but is available if you need it**. 
 +We're also implementing ''initializeStructureData'', which is not an override. 
 +We also have 2 constructors: 1 for our own pieces, and one for registry. 
 +A basic template would be:
  
 <code java> <code java>
-list_1.add(new MyGenerator.Piece(structureManager_1, identifier, blockPos, rotation_1))+public static class MyPiece extends SimpleStructurePiece { 
-</code>+  private final BlockRotation rotation
 +  private final Identifier template;
  
-标识符是我们最近创建的路径。+  public MyPiece(StructureManager structureManager, CompoundTag compoundTag) { 
 +    super(ExampleMod.MY_PIECE, compoundTag); 
 +    this.template = new Identifier(compoundTag.getString("Template")); 
 +    this.rotation = BlockRotation.valueOf(compoundTag.getString("Rot")); 
 +    this.initializeStructureData(structureManager); 
 +  }
  
-现在,我们将创建我们刚刚引用的作品; 创建一个名为Piece的类,该类扩展了SimpleStructurePiece//在您的生成器类中//.+  public MyPiece(StructureManager structureManager, BlockPos pos, Identifier template, BlockRotation rotation) { 
 +    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="true"]> +  } 
-public static class Piece extends SimpleStructurePiece { + 
-    private Rotation rotation; +  private void initializeStructureData(StructureManager structureManager) { 
-    private Identifier template; +    Structure structure structureManager.getStructureOrBlank(this.template); 
-     +    StructurePlacementData placementData = (new StructurePlacementData()
-    public Piece(StructureManager structureManager_1, Identifier identifier_1, BlockPos blockPos_1, Rotation rotation_1) { +      .setRotation(this.rotation
-        super(MyModClass.myStructurePieceType, 0); +      .setMirror(BlockMirror.NONE
-         +      .addProcessor(BlockIgnoreStructureProcessor.IGNORE_STRUCTURE_BLOCKS); 
-        this.pos blockPos_1; +    this.setStructureData(structure, this.pos, placementData); 
-        this.rotation = rotation_1; +  
-        this.template = identifier_1; + 
-         +  protected void toNbt(CompoundTag tag) { 
-        this.setStructureData(structureManager_1); +    super.toNbt(tag); 
-    +    tag.putString("Template", this.template.toString()); 
-     +    tag.putString("Rot", this.rotation.name()); 
-    public Piece(StructureManager structureManager_1, CompoundTag compoundTag_1{ +  
-        super(MyModClass.myStructurePieceType, compoundTag_1); + 
-        this.identifier = new Identifier(compoundTag_1.getString("Template")); +  @Override 
-        this.rotation = Rotation.valueOf(compoundTag_1.getString("Rot")); +  protected void handleMetadata(String metadata, BlockPos posServerWorldAccess serverWorldAccess, Random random
-        this.setStructureData(structureManager_1); +      BlockBox boundingBox) { 
-    +  }
-     +
-    @Override +
-    protected void toNbt(CompoundTag compoundTag_1) { +
-        super.toNbt(compoundTag_1); +
-        compoundTag_1.putString("Template", this.template.toString()); +
-        compoundTag_1.putString("Rot", this.rotation.name()); +
-    +
-     +
-    public void setStructureData(StructureManager structureManager) { +
-        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, this.pos, structurePlacementData_1); +
-    } +
-     +
-    @Override +
-    protected void handleMetadata(String string_1, BlockPos blockPos_1IWorld iWorld_1, Random random_1MutableIntBoundingBox mutableIntBoundingBox_1) { +
-         +
-    } +
-     +
-    @Override +
-    public boolean generate(IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1, ChunkPos chunkPos_1) { +
-       +
-    }+
 } }
 </code> </code>
          
-handleMetadata是查看结构中的数据块并根据发现的内容执行任务的地方。 在原版结构中,数据块放置在箱子上方,因此可以用这种方法将它们填满战利品。+''handleMetadata'' is where you look at data blocks within your structure and can do tasks based on what you find. 
 +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's nbt file and it will generate loot when opened for the first time. (Don't open the chest before saving to the nbt file!) 
 +<code>/setblock ~ ~ ~ minecraft:chest[facing=north]{LootTable:"modid:loottable"}</code>
  
-<code java [enable_line_numbers="true"]> +We set the ''StructurePieceType'' to ''ExampleMod.MY_PIECE''; this is the variable that holds your registered structure piece
-@Override +
-public boolean generate(IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1, ChunkPos chunkPos_1) { +
-    int yHeight = iWorld_1.getTop(Heightmap.Type.WORLD_SURFACE_WG, this.pos.getX() + 8, this.pos.getZ() + 8); +
-    this.pos = this.pos.add(0, yHeight - 1, 0); +
-    return super.generate(iWorld_1, random_1, mutableIntBoundingBox_1, chunkPos_1); +
-+
-</code> +
-     +
-在这种情况下,我们仅获取块中间最高块的y位置,并从该位置生成结构。+
  
 ==== 注册功能 ==== ==== 注册功能 ====