Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to 1.21.4: "Getting Started" and "Blocks" #245

Merged
merged 7 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Folders
/node_modules
/.vitepress/cache
/.vitepress/.temp
/.vitepress/dist
.idea/
.obsidian/
Expand Down
4 changes: 2 additions & 2 deletions develop/blocks/block-entity-renderer.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authors:

# Block Entity Renderers {#block-entity-renderers}

Sometimes, using Minecraft's model format is not enough. If you need to add dynamic rendering to it, you will need to use a `BlockEntityRenderer`.
Sometimes, using Minecraft's model format is not enough. If you need to add dynamic rendering to your block's visuals, you will need to use a `BlockEntityRenderer`.

For example, let's make the Counter Block from the [Block Entities article](../blocks/block-entities) show the number of clicks on its top side.

Expand All @@ -24,7 +24,7 @@ Also, by including a constructor like this, it becomes possible to use the const

@[code transcludeWith=:::1](@/reference/latest/src/client/java/com/example/docs/FabricDocsBlockEntityRenderer.java)

Add the entrypoint to the `fabric.mod.json` file, so that the renderer is registered.
You should register block entity renderers in your `ClientModInitializer` class.

`BlockEntityRendererFactories` is a registry that maps each `BlockEntityType` with custom rendering code to its respective `BlockEntityRenderer`.

Expand Down
4 changes: 0 additions & 4 deletions develop/blocks/blockstates.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,6 @@ You'll also have to set a default state for the `activated` property in the cons

@[code transcludeWith=:::3](@/reference/latest/src/main/java/com/example/docs/block/custom/PrismarineLampBlock.java)

::: warning
Don't forget to register your block using the custom class instead of `Block`!
:::

### Using The Property {#using-the-property}

This example flips the boolean `activated` property when the player interacts with the block. We can override the `onUse` method for this:
Expand Down
15 changes: 11 additions & 4 deletions develop/blocks/first-block.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ We will not cover all the options here—you can view the class yourself to see

For example purposes, we will be creating a simple block that has the properties of dirt, but is a different material.

- We need a `RegistryKey<Block>` which is used as a unique identifier for our block, this is passed into `Registry.register` in the previous utility method.
- The `RegistryKey<Block>` is also required by the `AbstractBlock.Settings` builder.

::: tip
You can also use `AbstractBlock.Settings.copy(AbstractBlock block)` to copy the settings of an existing block, in this case, we could have used `Blocks.DIRT` to copy the settings of dirt, but for example purposes we'll use the builder.
:::
Expand All @@ -57,13 +60,15 @@ You can also use `AbstractBlock.Settings.copy(AbstractBlock block)` to copy the

To automatically create the block item, we can pass `true` to the `shouldRegisterItem` parameter of the `register` method we created in the previous step.

### Adding Your Block to an Item Group {#adding-your-block-to-an-item-group}
### Adding Your Block's Item to an Item Group {#adding-your-block-s-item-to-an-item-group}

Since the `BlockItem` is automatically created and registered, to add it to an item group, you must use the `Block.asItem()` method to get the `BlockItem` instance.

For this example, we'll use a custom item group created in the [Custom Item Groups](../items/custom-item-groups) page.

@[code transcludeWith=:::3](@/reference/latest/src/main/java/com/example/docs/block/ModBlocks.java)
@[code transcludeWith=:::6](@/reference/latest/src/main/java/com/example/docs/block/ModBlocks.java)

You should place this within the `initialize()` function of your class.

---

Expand Down Expand Up @@ -118,7 +123,9 @@ This file should be located in the `assets/mod_id/blockstates` folder, and its n

@[code](@/reference/latest/src/main/resources/assets/fabric-docs-reference/blockstates/condensed_dirt.json)

Blockstates are really complex, which is why they are addressed in an upcoming page: [Block States](./blockstates)
::: tip
Blockstates are incredibly complex, which is why they will be covered next in [their own seperate page](./blockstates).
:::

Restarting the game, or reloading via <kbd>F3</kbd>+<kbd>T</kbd> to apply changes - you should be able to see the block texture in the inventory and physically in the world:

Expand Down Expand Up @@ -167,4 +174,4 @@ The file has the same format as the harvesting tool file - a list of items to be

## Extra Notes {#extra-notes}

If you're adding multiple blocks to your mod, you may want to consider using [Data Generation](https://fabricmc.net/wiki/tutorial:datagen_setup) to automate the process of creating block and item models, blockstate definitions, and loot tables.
If you're adding multiple blocks to your mod, you may want to consider using [Data Generation](../data-generation/setup) to automate the process of creating block and item models, blockstate definitions, and loot tables.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ To start developing mods with Fabric, you will need to set up a development envi

## Installing JDK 21 {#installing-jdk-21}

To develop mods for Minecraft 1.21, you will need JDK 21.
To develop mods for Minecraft 1.21.4, you will need JDK 21.

If you need help installing Java, you can refer to the various Java installation guides in the [player guides section](../../players/index).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,68 +25,91 @@ public class ModBlocks {
// :::1

// :::2
public static final RegistryKey<Block> CONDENSED_DIRT_KEY = RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(FabricDocsReference.MOD_ID, "condensed_dirt"));
public static final RegistryKey<Block> CONDENSED_DIRT_KEY = RegistryKey.of(
RegistryKeys.BLOCK,
Identifier.of(FabricDocsReference.MOD_ID, "condensed_dirt")
);

public static final Block CONDENSED_DIRT = register(
new Block(AbstractBlock.Settings.create().registryKey(CONDENSED_DIRT_KEY).sounds(BlockSoundGroup.GRASS)),
"condensed_dirt",
CONDENSED_DIRT_KEY,
true
);

// :::2
// :::3
public static final RegistryKey<Block> CONDENSED_OAK_LOG_KEY = RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(FabricDocsReference.MOD_ID, "condensed_oak_log"));
public static final RegistryKey<Block> CONDENSED_OAK_LOG_KEY = RegistryKey.of(
RegistryKeys.BLOCK,
Identifier.of(FabricDocsReference.MOD_ID, "condensed_oak_log")
);

public static final Block CONDENSED_OAK_LOG = register(
new PillarBlock(
AbstractBlock.Settings.create()
.registryKey(CONDENSED_OAK_LOG_KEY)
.sounds(BlockSoundGroup.WOOD)
), "condensed_oak_log", true
), CONDENSED_OAK_LOG_KEY, true
);

// :::3
// :::4
public static final RegistryKey<Block> PRISMARINE_LAMP_KEY = RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(FabricDocsReference.MOD_ID, "prismarine_lamp"));
public static final RegistryKey<Block> PRISMARINE_LAMP_KEY = RegistryKey.of(
RegistryKeys.BLOCK,
Identifier.of(FabricDocsReference.MOD_ID, "prismarine_lamp")
);
public static final Block PRISMARINE_LAMP = register(
new PrismarineLampBlock(
AbstractBlock.Settings.create()
.registryKey(PRISMARINE_LAMP_KEY)
.sounds(BlockSoundGroup.LANTERN)
.luminance(PrismarineLampBlock::getLuminance)
), "prismarine_lamp", true
), PRISMARINE_LAMP_KEY, true
);
// :::4
public static final RegistryKey<Block> ENGINE_BLOCK_KEY = RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(FabricDocsReference.MOD_ID, "engine"));
public static final RegistryKey<Block> ENGINE_BLOCK_KEY = RegistryKey.of(
RegistryKeys.BLOCK,
Identifier.of(FabricDocsReference.MOD_ID, "engine")
);
public static final Block ENGINE_BLOCK = register(
new EngineBlock(AbstractBlock.Settings.create().registryKey(ENGINE_BLOCK_KEY)), "engine", true
new EngineBlock(AbstractBlock.Settings.create().registryKey(ENGINE_BLOCK_KEY)), ENGINE_BLOCK_KEY, true
);

// :::5
public static final RegistryKey<Block> COUNTER_BLOCK_KEY = RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(FabricDocsReference.MOD_ID, "counter_block"));
public static final RegistryKey<Block> COUNTER_BLOCK_KEY = RegistryKey.of(
RegistryKeys.BLOCK,
Identifier.of(FabricDocsReference.MOD_ID, "counter_block")
);
public static final Block COUNTER_BLOCK = register(
new CounterBlock(AbstractBlock.Settings.create().registryKey(COUNTER_BLOCK_KEY)), "counter_block", true
new CounterBlock(AbstractBlock.Settings.create().registryKey(COUNTER_BLOCK_KEY)), COUNTER_BLOCK_KEY, true
);
// :::5

// :::1
public static Block register(Block block, String name, boolean shouldRegisterItem) {
// Register the block and its item.
Identifier id = Identifier.of(FabricDocsReference.MOD_ID, name);

public static Block register(Block block, RegistryKey<Block> registryKey, boolean shouldRegisterItem) {
// Sometimes, you may not want to register an item for the block.
// Eg: if it's a technical block like `minecraft:air` or `minecraft:end_gateway`
if (shouldRegisterItem) {
BlockItem blockItem = new BlockItem(block, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, id)));
Registry.register(Registries.ITEM, id, blockItem);
// Items need to be registered with a different type of registry key, but the ID
// can be the same.
RegistryKey<Item> itemRegistryKey = RegistryKey.of(RegistryKeys.ITEM, registryKey.getValue());
BlockItem blockItem = new BlockItem(block, new Item.Settings().registryKey(itemRegistryKey));
Registry.register(Registries.ITEM, itemRegistryKey, blockItem);
}

return Registry.register(Registries.BLOCK, id, block);
return Registry.register(Registries.BLOCK, registryKey, block);
}

// :::1
public static void initialize() {
// :::3
setupItemGroups();
}

public static void setupItemGroups() {
// :::6
ItemGroupEvents.modifyEntriesEvent(ModItems.CUSTOM_ITEM_GROUP_KEY).register((itemGroup) -> {
itemGroup.add(ModBlocks.CONDENSED_DIRT.asItem());
});
// :::3
// :::6

ItemGroupEvents.modifyEntriesEvent(ModItems.CUSTOM_ITEM_GROUP_KEY).register((itemGroup) -> {
itemGroup.add(ModBlocks.CONDENSED_OAK_LOG.asItem());
Expand Down