User Tools

Site Tools


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 revisionBoth sides next revision
tutorial:structures [2019/02/16 20:58] asietutorial:structures [2019/05/26 16:34] – Syntax highlighting, more consistent formatting jamieswhiteshirt
Line 26: Line 26:
 For getStructureStartFactory, most vanilla structures make a class that extends StructureStart inside their Feature class: For getStructureStartFactory, most vanilla structures make a class that extends StructureStart inside their Feature class:
  
-  public static class MyStructureStart extends StructureStart +<code java [enable_line_numbers="true"]> 
-    +public static class MyStructureStart extends StructureStart { 
-        public MyStructureStart (StructureFeature<?> structureFeature_1, int int_1, int int_2, Biome biome_1, MutableIntBoundingBox mutableIntBoundingBox_1, int int_3, long long_1) +    public MyStructureStart (StructureFeature<?> structureFeature_1, int int_1, int int_2, Biome biome_1, MutableIntBoundingBox mutableIntBoundingBox_1, int int_3, long long_1) { 
-        +        super(structureFeature_1, int_1, int_2, biome_1, mutableIntBoundingBox_1, int_3, long_1);
-            super(structureFeature_1, int_1, int_2, biome_1, mutableIntBoundingBox_1, int_3, long_1); +
-        } +
-        @Override +
-        public void initialize(ChunkGenerator<?> chunkGenerator, StructureManager structureManager, int chunkX, int chunkZ, Biome biome) +
-        { +
-            DefaultFeatureConfig defaultFeatureConfig = chunkGenerator.getStructureConfig(biome, MyMainclass.myFeature); +
-            int x = chunkX * 16; +
-            int z = chunkZ * 16; +
-            BlockPos startingPos = new BlockPos(x, 0, z); +
-            Rotation rotation = Rotation.values()[this.random.nextInt(Rotation.values().length)]; +
-            MyGenerator.addParts(structureManager, startingPos, rotation, this.children, this.random, defaultFeatureConfig); +
-            this.setBoundingBoxFromChildren(); +
-        }+
     }     }
 +    @Override
 +    public void initialize(ChunkGenerator<?> chunkGenerator, StructureManager structureManager, int chunkX, int chunkZ, Biome biome) {
 +        DefaultFeatureConfig defaultFeatureConfig = chunkGenerator.getStructureConfig(biome, MyMainclass.myFeature);
 +        int x = chunkX * 16;
 +        int z = chunkZ * 16;
 +        BlockPos startingPos = new BlockPos(x, 0, z);
 +        Rotation rotation = Rotation.values()[this.random.nextInt(Rotation.values().length)];
 +        MyGenerator.addParts(structureManager, startingPos, rotation, this.children, this.random, defaultFeatureConfig);
 +        this.setBoundingBoxFromChildren();
 +    }
 +}
 +</code>
          
 This is called when the world attempts to spawn in a new structure, and is the gap between your Feature and Generator. The reference to the variable in your main class doesn't exist yet, but we'll create it at the end. You can also just set the config equal to a new DefaultFeatureConfig. You can return this in getStructureStartFactory with return MyStructureStart::new. This is called when the world attempts to spawn in a new structure, and is the gap between your Feature and Generator. The reference to the variable in your main class doesn't exist yet, but we'll create it at the end. You can also just set the config equal to a new DefaultFeatureConfig. You can return this in getStructureStartFactory with return MyStructureStart::new.
Line 59: Line 58:
   * Some sort of setup method - addParts is a good name:   * Some sort of setup method - addParts is a good name:
  
-  public static void addParts(StructureManager structureManager_1, BlockPos blockPos_1, Rotation rotation_1,  +<code java> 
-  List<StructurePiece> list_1, Random random_1, DefaultFeatureConfig featureConfig)+public static void addParts(StructureManager structureManager_1, BlockPos blockPos_1, Rotation rotation_1,  
 +    List<StructurePiece> list_1, Random random_1, DefaultFeatureConfig featureConfig)
          
-    }+} 
 +</code>
          
 In your addParts method, you can choose which structure pieces are added to your generation process. You can add a piece like this: In your addParts method, you can choose which structure pieces are added to your generation process. You can add a piece like this:
  
-  list_1.add(new MyGenerator.Piece(structureManager_1, identifier, blockPos, rotation_1)); +<code java> 
 +list_1.add(new MyGenerator.Piece(structureManager_1, identifier, blockPos, rotation_1)); 
 +</code>
      
 where the identifier is the path we created recently. where the identifier is the path we created recently.
Line 74: Line 77:
 Override required methods, and add a constructor that takes in a StructureManager, Identifier, BlockPos, and Rotation. **toNbt isn't required but is available if you need it**. We're also implementing our own setStructureData with different arguments, so it's not an override. We also have 2 constructors: 1 for our own pieces, and one for registry. A basic template would be: Override required methods, and add a constructor that takes in a StructureManager, Identifier, BlockPos, and Rotation. **toNbt isn't required but is available if you need it**. We're also implementing our own setStructureData with different arguments, so it's not an override. We also have 2 constructors: 1 for our own pieces, and one for registry. A basic template would be:
  
-  public static class Piece extends SimpleStructurePiece { +<code java [enable_line_numbers="true"]> 
-        private Rotation rotation; +public static class Piece extends SimpleStructurePiece { 
-        private Identifier template;+    private Rotation rotation; 
 +    private Identifier template
 +     
 +    public Piece(StructureManager structureManager_1, Identifier identifier_1, BlockPos blockPos_1, Rotation rotation_1) { 
 +        super(MyModClass.myStructurePieceType, 0);
                  
-        public Piece(StructureManager structureManager_1, Identifier identifier_1, BlockPos blockPos_1, Rotation rotation_1) { +        this.pos = blockPos_1; 
-            super(MyModClass.myStructurePieceType, 0); +        this.rotation = rotation_1; 
-             +        this.template = identifier_1;
-            this.pos = blockPos_1; +
-            this.rotation = rotation_1; +
-            this.template = identifier_1; +
-             +
-            this.setStructureData(structureManager_1); +
-        }+
                  
-        public Piece(StructureManager structureManager_1, CompoundTag compoundTag_1) { +        this.setStructureData(structureManager_1); 
-            super(MyModClass.myStructurePieceType, compoundTag_1); +    } 
-            this.identifier = new Identifier(compoundTag_1.getString("Template")); +     
-            this.rotation = Rotation.valueOf(compoundTag_1.getString("Rot")); +    public Piece(StructureManager structureManager_1, CompoundTag compoundTag_1) { 
-            this.setStructureData(structureManager_1); +        super(MyModClass.myStructurePieceType, compoundTag_1); 
-        +        this.identifier = new Identifier(compoundTag_1.getString("Template")); 
-         +        this.rotation = Rotation.valueOf(compoundTag_1.getString("Rot")); 
-        @Override +        this.setStructureData(structureManager_1); 
-        protected void toNbt(CompoundTag compoundTag_1) { +    
-            super.toNbt(compoundTag_1); +     
-            compoundTag_1.putString("Template", this.template.toString()); +    @Override 
-            compoundTag_1.putString("Rot", this.rotation.name()); +    protected void toNbt(CompoundTag compoundTag_1) { 
-        +        super.toNbt(compoundTag_1); 
-         +        compoundTag_1.putString("Template", this.template.toString()); 
-        public void setStructureData(StructureManager structureManager) +        compoundTag_1.putString("Rot", this.rotation.name()); 
-        +    
-            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); +    public void setStructureData(StructureManager structureManager) { 
-            this.setStructureData(structure_1, this.pos, structurePlacementData_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, this.pos, structurePlacementData_1); 
-        @Override +    
-        protected void handleMetadata(String string_1, BlockPos blockPos_1, IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1) { +     
-        }+    @Override 
 +    protected void handleMetadata(String string_1, BlockPos blockPos_1, IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1) {
                  
-        @Override 
-        public boolean generate(IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1, ChunkPos chunkPos_1) 
-        { 
-           
-        } 
     }     }
 +    
 +    @Override
 +    public boolean generate(IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1, ChunkPos chunkPos_1) {
 +      
 +    }
 +}
 +</code>
          
 handleMetadata is where you look at data blocks within your structure and do tasks based on what you find. In vanilla structures, data blocks are placed above chests so they can be filled with loot in this method. handleMetadata is where you look at data blocks within your structure and do tasks based on what you find. In vanilla structures, data blocks are placed above chests so they can be filled with loot in this method.
Line 124: Line 128:
 We set the StructurePieceType to MyModClass.myStructurePiece type; this is the variable that holds your registered structure piece. We'll handle that after we finish the generate function, which sets the position of your structure and generates it: We set the StructurePieceType to MyModClass.myStructurePiece type; this is the variable that holds your registered structure piece. We'll handle that after we finish the generate function, which sets the position of your structure and generates it:
  
-  @Override +<code java [enable_line_numbers="true"]> 
-        public boolean generate(IWorld iWorld_1, Random random_1, MutableIntBoundingBox mutableIntBoundingBox_1, ChunkPos chunkPos_1) +@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); +    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); +    this.pos = this.pos.add(0, yHeight - 1, 0); 
-            return  super.generate(iWorld_1, random_1, mutableIntBoundingBox_1, chunkPos_1); +    return super.generate(iWorld_1, random_1, mutableIntBoundingBox_1, chunkPos_1); 
-        }+} 
 +</code>
          
 In this case, we simply get the y position of the highest block in the middle of our chunk and generate the structure off that position.  In this case, we simply get the y position of the highest block in the middle of our chunk and generate the structure off that position. 
Line 145: Line 150:
  
 Registering piece type: Registering piece type:
-  public static final StructurePieceType myStructurePieceType = Registry.register(Registry.STRUCTURE_PIECE, "my_piece", MyGenerator.Piece::new);+<code java> 
 +public static final StructurePieceType myStructurePieceType = Registry.register(Registry.STRUCTURE_PIECE, "my_piece", MyGenerator.Piece::new); 
 +</code>
      
 Registering feature: Registering feature:
-  public static final StructureFeature<DefaultFeatureConfig> myFeature = Registry.register(Registry.FEATURE, "my_feature", new MyFeature());+<code java> 
 +public static final StructureFeature<DefaultFeatureConfig> myFeature = Registry.register(Registry.FEATURE, "my_feature", new MyFeature()); 
 +</code>
      
 Registering structure: Registering structure:
-  public static final StructureFeature<?> myStructure = Registry.register(Registry.STRUCTURE_FEATURE, "my_structure", myFeature);+<code java> 
 +public static final StructureFeature<?> myStructure = Registry.register(Registry.STRUCTURE_FEATURE, "my_structure", myFeature); 
 +</code>
      
 To put your feature in the features list, you can use: To put your feature in the features list, you can use:
-  Feature.STRUCTURES.put("My Awesome Feature", myFeature);+<code java> 
 +Feature.STRUCTURES.put("My Awesome Feature", myFeature); 
 +</code>
      
 For testing, it's a good idea to register your feature to every biome and set the spawn rate to 100% so you can be sure it's spawning and working. You probably don't want your structure floating in the water, so we'll also filter that out. Add it to every biome by iterating over the biome list and adding it as a feature and generation step: For testing, it's a good idea to register your feature to every biome and set the spawn rate to 100% so you can be sure it's spawning and working. You probably don't want your structure floating in the water, so we'll also filter that out. Add it to every biome by iterating over the biome list and adding it as a feature and generation step:
  
-  for(Biome biome : Registry.BIOME) +<code java [enable_line_numbers="true"]> 
- +for(Biome biome : Registry.BIOME) { 
- if(biome.getCategory() != Biome.Category.OCEAN && biome.getCategory() != Biome.Category.RIVER) +    if(biome.getCategory() != Biome.Category.OCEAN && biome.getCategory() != Biome.Category.RIVER) { 
- +        biome.addStructureFeature(myFeature, new DefaultFeatureConfig()); 
- biome.addStructureFeature(myFeature, new DefaultFeatureConfig()); +        biome.addFeature(GenerationStep.Feature.SURFACE_STRUCTURES, Biome.configureFeature(myFeature, new DefaultFeatureConfig(), Decorator.CHANCE_PASSTHROUGH, new ChanceDecoratorConfig(0))); 
- biome.addFeature(GenerationStep.Feature.SURFACE_STRUCTURES, Biome.configureFeature(myFeature, new DefaultFeatureConfig(), Decorator.CHANCE_PASSTHROUGH, new ChanceDecoratorConfig(0))); +    
- +} 
- }+</code>
  
 ChanceDecoratorConfig's argument is basically how many chunks it will skip over before generating. 0 is every chunk, 1 is every other, and 100 is every 100. ChanceDecoratorConfig's argument is basically how many chunks it will skip over before generating. 0 is every chunk, 1 is every other, and 100 is every 100.
Line 171: Line 184:
 You need to add your structure as a feature so your biome knows it exists, and then as a generation step so it's actually generated. You need to add your structure as a feature so your biome knows it exists, and then as a generation step so it's actually generated.
  
-Load into your world, and if all went well, you should be met with a //lot// of Igloos.  +Load into your world, and if all went well, you should be met with a //lot// of Igloos.
- +
- +
- +
tutorial/structures.txt · Last modified: 2022/11/05 12:06 by jab125