tutorial:structures_old
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
tutorial:structures_old [2024/08/25 13:35] – removed - external edit (Unknown date) 127.0.0.1 | tutorial:structures_old [2024/08/25 13:52] (current) – ↷ Links adapted because of a move operation 52.167.144.180 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Adding Structure Features [1.16.3] ====== | ||
+ | :!: //**For versions 1.18 and beyond, the Fabric Structure API no longer exists and structures can be done entirely in datapacks. See [[https:// | ||
+ | |||
+ | We’re going to look at registering and placing structures in your world. | ||
+ | |||
+ | To view examples of vanilla structures in action, '' | ||
+ | |||
+ | You are going to need a feature and generator for the most basic structure. | ||
+ | The feature handles the process of registering the structure and loading it in when the world is generating. | ||
+ | The generator handles the placement of blocks or loading in a structure file if you choose to do so. | ||
+ | |||
+ | Note that this tutorial depends on [[https:// | ||
+ | If the API doesn' | ||
+ | |||
+ | ===== Creating a Feature ===== | ||
+ | To create a basic feature, we recommend creating a class that extends '' | ||
+ | Various vanilla structures, such as shipwrecks, igloos, and temples, use '' | ||
+ | |||
+ | You will have to override '' | ||
+ | For '' | ||
+ | |||
+ | <code java> | ||
+ | public class MyFeature extends StructureFeature< | ||
+ | public MyFeature(Codec< | ||
+ | super(codec); | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public StructureFeature.StructureStartFactory< | ||
+ | return Start::new; | ||
+ | } | ||
+ | |||
+ | public static class Start extends StructureStart< | ||
+ | public Start(StructureFeature< | ||
+ | long seed) { | ||
+ | super(feature, | ||
+ | } | ||
+ | |||
+ | // Called when the world attempts to spawn in a new structure, and is the gap between your feature and generator. | ||
+ | public void init(DynamicRegistryManager registryManager, | ||
+ | int chunkZ, Biome biome, DefaultFeatureConfig config) { | ||
+ | int x = chunkX * 16; | ||
+ | int z = chunkZ * 16; | ||
+ | int y = chunkGenerator.getHeight(x, | ||
+ | BlockPos pos = new BlockPos(x, y, z); | ||
+ | BlockRotation rotation = BlockRotation.random(this.random); | ||
+ | MyGenerator.addPieces(manager, | ||
+ | this.setBoundingBoxFromChildren(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Creating a Generator ===== | ||
+ | As you have probably noticed, we need to create a generator. | ||
+ | |||
+ | This is where structure files and generating straight from a '' | ||
+ | |||
+ | * If you want, you can simply override '' | ||
+ | * Use structure files. These are rather powerful at this point and are highly recommended. | ||
+ | |||
+ | In this tutorial, we'll use a structure file. | ||
+ | It doesn' | ||
+ | * An identifier that points to your structure file; use ''" | ||
+ | * Some sort of setup method - '' | ||
+ | |||
+ | <code java> | ||
+ | public class MyGenerator { | ||
+ | private static final Identifier IGLOO_TOP = new Identifier(" | ||
+ | |||
+ | public static void addPieces(StructureManager manager, BlockPos pos, BlockRotation rotation, List< | ||
+ | pieces.add(new MyPiece(manager, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In your '' | ||
+ | |||
+ | We're now going to create the piece we just referenced; make a class called '' | ||
+ | |||
+ | 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> | ||
+ | public static class MyPiece extends SimpleStructurePiece { | ||
+ | private final BlockRotation rotation; | ||
+ | private final Identifier template; | ||
+ | |||
+ | public MyPiece(StructureManager structureManager, | ||
+ | super(ExampleMod.MY_PIECE, | ||
+ | this.template = new Identifier(compoundTag.getString(" | ||
+ | this.rotation = BlockRotation.valueOf(compoundTag.getString(" | ||
+ | this.initializeStructureData(structureManager); | ||
+ | } | ||
+ | |||
+ | public MyPiece(StructureManager structureManager, | ||
+ | super(ExampleMod.MY_PIECE, | ||
+ | this.pos = pos; | ||
+ | this.rotation = rotation; | ||
+ | this.template = template; | ||
+ | |||
+ | this.initializeStructureData(structureManager); | ||
+ | } | ||
+ | |||
+ | private void initializeStructureData(StructureManager structureManager) { | ||
+ | Structure structure = structureManager.getStructureOrBlank(this.template); | ||
+ | StructurePlacementData placementData = (new StructurePlacementData()) | ||
+ | .setRotation(this.rotation) | ||
+ | .setMirror(BlockMirror.NONE) | ||
+ | .addProcessor(BlockIgnoreStructureProcessor.IGNORE_STRUCTURE_BLOCKS); | ||
+ | this.setStructureData(structure, | ||
+ | } | ||
+ | |||
+ | protected void toNbt(CompoundTag tag) { | ||
+ | super.toNbt(tag); | ||
+ | tag.putString(" | ||
+ | tag.putString(" | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | protected void handleMetadata(String metadata, BlockPos pos, ServerWorldAccess serverWorldAccess, | ||
+ | BlockBox boundingBox) { | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | | ||
+ | '' | ||
+ | This can be good for dynamic stuff such as placing certain mobs based on what mod is on and so on. | ||
+ | |||
+ | 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' | ||
+ | < | ||
+ | |||
+ | We set the '' | ||
+ | |||
+ | ===== Registering Structures ===== | ||
+ | The last step is to register our structures. We're going to need to register: | ||
+ | |||
+ | * structure | ||
+ | * piece | ||
+ | * configured structure | ||
+ | |||
+ | <code java> | ||
+ | public class ExampleMod implements ModInitializer { | ||
+ | public static final StructurePieceType MY_PIECE = MyGenerator.MyPiece:: | ||
+ | private static final StructureFeature< | ||
+ | private static final ConfiguredStructureFeature<?, | ||
+ | |||
+ | @Override | ||
+ | public void onInitialize() { | ||
+ | Registry.register(Registry.STRUCTURE_PIECE, | ||
+ | FabricStructureBuilder.create(new Identifier(" | ||
+ | .step(GenerationStep.Feature.SURFACE_STRUCTURES) | ||
+ | .defaultConfig(32, | ||
+ | .adjustsSurface() | ||
+ | .register(); | ||
+ | |||
+ | RegistryKey< | ||
+ | new Identifier(" | ||
+ | BuiltinRegistries.add(BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Adding a configured feature to biomes ===== | ||
+ | In this tutorial, we add our structure to all biomes. | ||
+ | |||
+ | <code java> | ||
+ | public class ExampleMod implements ModInitializer { | ||
+ | [...] | ||
+ | |||
+ | @Override | ||
+ | public void onInitialize() { | ||
+ | [...] | ||
+ | |||
+ | BiomeModifications.addStructure(BiomeSelectors.all(), | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Result ===== | ||
+ | You should be met with igloos. | ||
+ | You can use below command to find your structure in the world. | ||
+ | |||
+ | < | ||
+ | /locate tutorial: | ||
+ | </ | ||
+ | |||
+ | {{tutorial: | ||