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

Blocks #118

Merged
merged 40 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
30981a3
"Creating Your First Item" page.
IMB11 Jun 14, 2024
f30f10e
Merge branch 'main' into items
IMB11 Jun 14, 2024
6553e91
Checkstyle fixes + Food pages
IMB11 Jun 14, 2024
33af9e9
Clarification.
IMB11 Jun 14, 2024
a407885
Fix translation key in first-item.md
IMB11 Jun 14, 2024
5c38379
Armor page
IMB11 Jun 14, 2024
6ba51be
Fixes and armor guide.
IMB11 Jun 14, 2024
97ca5f9
Knockback resistance comment.
IMB11 Jun 14, 2024
ac10fb8
Tools guide.
IMB11 Jun 14, 2024
bb06fff
Reference to enums and vanilla materials.
IMB11 Jun 15, 2024
d486e16
Text
IMB11 Jun 15, 2024
19533fd
Add medium-zoom, finish item and item group guides.
IMB11 Jun 15, 2024
1958903
Add z-index for medium-zoom overlay and image
IMB11 Jun 15, 2024
a99ae44
Add z-index to prevent image overlap
IMB11 Jun 15, 2024
0298c13
Update item group display name
IMB11 Jun 15, 2024
6390920
Mention maxCount
IMB11 Jun 15, 2024
315ef4a
Recipes.
IMB11 Jun 15, 2024
b22e9a6
Rearranged order of recipe resources in first-item.md
IMB11 Jun 15, 2024
3918385
Fixes + Use DownloadEntry elsewhere.
IMB11 Jun 15, 2024
93b9903
Add custom item interactions page and LightningStick class
IMB11 Jun 15, 2024
f5e69a8
Merge branch 'main' into items
IMB11 Jun 15, 2024
fac92cd
Merge branch 'main' into items
IMB11 Jun 15, 2024
b405de9
Fix pljson
IMB11 Jun 15, 2024
6d17d6d
Lint fixes
IMB11 Jun 15, 2024
a046541
Add dicedpixels as an author in first-item.md
IMB11 Jun 15, 2024
cdae1ee
Update reference/latest/src/main/java/com/example/docs/item/ModItems.…
IMB11 Jun 15, 2024
a13b63b
some improvements
IMB11 Jun 15, 2024
56b90bd
Vidstack + change suspicious substance texture.
IMB11 Jun 18, 2024
5dc0863
Switch to switches.
IMB11 Jun 18, 2024
d9ca903
Checkstyle fixes.
IMB11 Jun 18, 2024
2bd53d7
Fix some layout issues and typos.
IMB11 Jun 18, 2024
bd0d67b
Metadata issue.
IMB11 Jun 18, 2024
e50d5d0
First block page.
IMB11 Jun 19, 2024
4e954fd
Update file paths for item and block models
IMB11 Jun 19, 2024
8c74917
Blockstates
IMB11 Jun 19, 2024
e41cdbb
nl
IMB11 Jun 19, 2024
9520120
Merge branch 'main' into blocks
IMB11 Jul 1, 2024
c75caa5
Merge branch 'main' into blocks
IMB11 Jul 1, 2024
ba6e8c0
Merge branch 'main' into blocks
IMB11 Jul 2, 2024
f9ceb74
Lint fixes
IMB11 Jul 2, 2024
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
14 changes: 14 additions & 0 deletions .vitepress/sidebars/develop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ export default [
},
],
},
{
text: "develop.blocks",
collapsed: true,
items: [
{
text: "develop.blocks.first-block",
link: "/develop/blocks/first-block"
},
{
text: "develop.blocks.blockstates",
link: "/develop/blocks/blockstates"
}
]
},
{
text: "develop.entities",
collapsed: true,
Expand Down
127 changes: 127 additions & 0 deletions develop/blocks/blockstates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
title: Block States
description: Learn why blockstates are a great way to add visual functionality to your blocks.
authors:
- IMB11
---

# Block States

Check failure on line 8 in develop/blocks/blockstates.md

View workflow job for this annotation

GitHub Actions / markdownlint

Custom rule

develop/blocks/blockstates.md:8:1 search-replace Custom rule [missing-heading-anchor: Add anchors to headings. Use lowercase characters, numbers and dashes] [Context: "column: 1 text:'# Block States'"] https://github.com/OnkarRuikar/markdownlint-rule-search-replace

A block state is a piece of data attached to a singular block in the Minecraft world containing information on the block in the form of properties - some examples of properties vanilla stores in block states:

- Rotation: Mostly used for logs and other natural blocks.
- Activated: Heavily used in redstone devices, and blocks such as the furnace or smoker.
- Age: Used in crops, plants, saplings, kelp etc.

You can probably see why they are useful - they avoid the need to store NBT data in a block entity - reducing the world size, and preventing TPS issues!

Blockstate definitions are found in the `assets/<mod id here>/blockstates` folder.

## Example: Pillar Block

Check failure on line 20 in develop/blocks/blockstates.md

View workflow job for this annotation

GitHub Actions / markdownlint

Custom rule

develop/blocks/blockstates.md:20:1 search-replace Custom rule [missing-heading-anchor: Add anchors to headings. Use lowercase characters, numbers and dashes] [Context: "column: 1 text:'## Example: Pillar Block'"] https://github.com/OnkarRuikar/markdownlint-rule-search-replace

<!-- Note: This example could be used for a custom recipe types guide, a condensor machine block with a custom "Condensing" recipe? -->

Minecraft has some custom classes already that allow you quickly create certain types of blocks - this example goes through the creation of a block with the `axis` property by creating a "Condensed Oak Log" block.

The vanilla `PillarBlock` class allows the block to be placed in the X, Y or Z axis.

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

Pillar blocks have two textures, top and side - they use the `block/cube_column` model.

As always, with all block textures, the texture files can be found in `assets/<mod id here>/textures/block`

<DownloadEntry type="Textures" visualURL="/assets/develop/blocks/blockstates_0_large.png" downloadURL="/assets/develop/blocks/condensed_oak_log_textures.zip" />

Since the pillar block has two positions, horizontal and vertical, we'll need to make two separate model files:

- `condensed_oak_log_horizontal.json` which extends the `block/cube_column_horizontal` model.
- `condensed_oak_log.json` which extends the `block/cube_column` model.

An example of the `condensed_oak_log_horizontal.json` file:

@[code](@/reference/latest/src/main/resources/assets/fabric-docs-reference/models/block/condensed_oak_log_horizontal.json)

---

::: info
Remember, blockstate files can be found in the `assets/<mod id here>/blockstates` folder, the name of the blockstate file should match the block ID used when registering your block in the `ModBlocks` class. For instance, if the block ID is `condensed_oak_log`, the file should be named `condensed_oak_log.json`.

For a more in-depth look at all the modifiers available in the blockstate files, check out the [Minecraft Wiki - Models (Block States)](https://minecraft.wiki/w/Tutorials/Models#Block_states) page.
:::

Next, we need to create a blockstate file. The blockstate file is where the magic happens—pillar blocks have three axes, so we'll use specific models for the following situations:

- `axis=x` - When the block is placed along the X axis, we will rotate the model to face the positive X direction.
- `axis=y` - When the block is placed along the Y axis, we will use the normal vertical model.
- `axis=z` - When the block is placed along the Z axis, we will rotate the model to face the positive X direction.

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

As always, you'll need to create a translation for your block, and an item model which parents either of the two models.

![Example of Pillar block in-game](/assets/develop/blocks/blockstates_1.png)

## Custom Block States

Check failure on line 65 in develop/blocks/blockstates.md

View workflow job for this annotation

GitHub Actions / markdownlint

Custom rule

develop/blocks/blockstates.md:65:1 search-replace Custom rule [missing-heading-anchor: Add anchors to headings. Use lowercase characters, numbers and dashes] [Context: "column: 1 text:'## Custom Block States'"] https://github.com/OnkarRuikar/markdownlint-rule-search-replace

Custom block states are great if your block has unique properties - sometimes you may find that your block can re-use vanilla properties.

This example will create a unique boolean property called `activated` - when a player right-clicks on the block, the block will go from `activated=false` to `activated=true` - changing its texture accordingly.

### Creating The Property

Check failure on line 71 in develop/blocks/blockstates.md

View workflow job for this annotation

GitHub Actions / markdownlint

Custom rule

develop/blocks/blockstates.md:71:1 search-replace Custom rule [missing-heading-anchor: Add anchors to headings. Use lowercase characters, numbers and dashes] [Context: "column: 1 text:'### Creating The Property'"] https://github.com/OnkarRuikar/markdownlint-rule-search-replace

Firstly, you'll need to create the property itself - since this is a boolean, we'll use the `BooleanProperty.of` method.

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

Next, we have to append the property to the blockstate manager in the `appendProperties` method. You'll need to override the method to access the builder:

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

You'll also have to set a default state for the `activated` property in the constructor of your custom block.

@[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

Check failure on line 89 in develop/blocks/blockstates.md

View workflow job for this annotation

GitHub Actions / markdownlint

Custom rule

develop/blocks/blockstates.md:89:1 search-replace Custom rule [missing-heading-anchor: Add anchors to headings. Use lowercase characters, numbers and dashes] [Context: "column: 1 text:'### Using The Property'"] https://github.com/OnkarRuikar/markdownlint-rule-search-replace

This example flips the boolean `activated` property when the player interacts with the block. We can override the `onUse` method for this:

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

### Visualizing The Property

Check failure on line 95 in develop/blocks/blockstates.md

View workflow job for this annotation

GitHub Actions / markdownlint

Custom rule

develop/blocks/blockstates.md:95:1 search-replace Custom rule [missing-heading-anchor: Add anchors to headings. Use lowercase characters, numbers and dashes] [Context: "column: 1 text:'### Visualizing The Property'"] https://github.com/OnkarRuikar/markdownlint-rule-search-replace

Before creating the blockstate file, you will need to provide textures for both the activated and deactivated states of the block, as well as the block model.

<DownloadEntry type="Textures" visualURL="/assets/develop/blocks/blockstates_2_large.png" downloadURL="/assets/develop/blocks/prismarine_lamp_textures.zip" />

Use your knowledge of block models to create two models for the block: one for the activated state and one for the deactivated state. Once you've done that, you can begin creating the blockstate file.

Since you created a new property, you will need to update the blockstate file for the block to account for that property.

If you have multiple properties on a block, you'll need to account for all possible combinations. For example, `activated` and `axis` would lead to 6 combinations (two possible values for `activated` and three possible values for `axis`).

Since this block only has two possible variants, as it only has one property (`activated`), the blockstate JSON will look something like this:

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

---

Since the example block is a lamp, we also need to make it emit light when the `activated` property is true. This can be done through the block settings passed to the constructor when registering the block.

You can use the `luminance` method to set the light level emitted by the block, we can create a static method in the `PrismarineLampBlock` class to return the light level based on the `activated` property, and pass it as a method reference to the `luminance` method:

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

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

---

<!-- Note: This block can be a great starter for a redstone block interactivity page, maybe triggering the blockstate based on redstone input? -->

Once you've completed everything, the final result should look something like the following:

<VideoPlayer src="/assets/develop/blocks/blockstates_3.webm" title="Prismarine Lamp Block in-game" />
166 changes: 166 additions & 0 deletions develop/blocks/first-block.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
title: Creating Your First Block
description: Learn how to create your first custom block in Minecraft.
authors:
- IMB11
---

# Creating Your First Block

Check failure on line 8 in develop/blocks/first-block.md

View workflow job for this annotation

GitHub Actions / markdownlint

Custom rule

develop/blocks/first-block.md:8:1 search-replace Custom rule [missing-heading-anchor: Add anchors to headings. Use lowercase characters, numbers and dashes] [Context: "column: 1 text:'# Creating Your First Block'"] https://github.com/OnkarRuikar/markdownlint-rule-search-replace

Blocks are the building blocks of Minecraft (no pun intended) - just like everything else in Minecraft, they're stored in registries.

## Preparing Your Blocks Class

Check failure on line 12 in develop/blocks/first-block.md

View workflow job for this annotation

GitHub Actions / markdownlint

Custom rule

develop/blocks/first-block.md:12:1 search-replace Custom rule [missing-heading-anchor: Add anchors to headings. Use lowercase characters, numbers and dashes] [Context: "column: 1 text:'## Preparing Your Blocks Class'"] https://github.com/OnkarRuikar/markdownlint-rule-search-replace

If you've completed the [Creating Your First Item](../items/first-item.md) page, this process will feel extremely familiar - you will need to create a method that registers your block, and it's block item.

Check failure on line 14 in develop/blocks/first-block.md

View workflow job for this annotation

GitHub Actions / markdownlint

Custom rule

develop/blocks/first-block.md:14:25 search-replace Custom rule [no-file-extension-in-links: Don't add the file extension to links] [Context: "column: 25 text:'[Creating Your First Item](../items/first-item.md)'"] https://github.com/OnkarRuikar/markdownlint-rule-search-replace

You should put this method in a class called `ModBlocks` (or whatever you want to name it).

Mojang does something extremely similar like this with vanilla blocks; you can refer to the `Blocks` class to see how they do it.

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

---

Just like with items, you need to ensure that the class is loaded so that all static fields containing your block instances are initialized.

You can do this by creating a dummy `initialize` method, which can be called in your mod initializer to trigger the static initialization.

::: info
If you are unaware of what static initialization is, it is the process of initializing static fields in a class. This is done when the class is loaded by the JVM, and is done before any instances of the class are created.
:::

```java
public class ModBlocks {
// ...

public static void initialize() {}
}
```

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

## Creating And Registering Your Block

Check failure on line 42 in develop/blocks/first-block.md

View workflow job for this annotation

GitHub Actions / markdownlint

Custom rule

develop/blocks/first-block.md:42:1 search-replace Custom rule [missing-heading-anchor: Add anchors to headings. Use lowercase characters, numbers and dashes] [Context: "column: 1 text:'## Creating And Registering Your Block'"] https://github.com/OnkarRuikar/markdownlint-rule-search-replace

Similarly to items, blocks take a `Blocks.Settings` class in their constructor, which specifies properties about the block, such as its sound effects and mining level.

We will not cover all the options here—you can view the class yourself to see the various options, which should be self-explanatory.

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

::: 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.
:::

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

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

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.md) page.

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

---

You should now notice that your block is in the creative inventory, and can be placed in the world!

![Block in world without suitable model or texture.](/assets/develop/blocks/first_block_0.png)

There are a few issues though - the block item is not named, and the block has no texture, block model or item model.

## Adding Block Translations

To add a translation, you must create a translation key in your translation file - `assets/<mod id here>/lang/en_us.json`.

Minecraft will use this translation in the creative inventory and other places where the block name is displayed, such as command feedback.

```json
{
"block.mod_id.condensed_dirt": "Condensed Dirt"
}
```

You can either restart the game or build your mod and press <kbd>F3</kbd> + <kbd>T</kbd> to apply changes - and you should see that the block has a name in the creative inventory and other places such as the statistics screen.

## Models and Textures

All block textures can be found in the `assets/<mod id here>/textures/block` folder - an example texture for the "Condensed Dirt" block is free to use.

<DownloadEntry type="Texture" visualURL="/assets/develop/blocks/first_block_1.png" downloadURL="/assets/develop/blocks/first_block_1_small.png" />

To make the texture show up in-game, you must create a block and item model which can be found in the respective locations for the "Condensed Dirt" block:

- `assets/<mod id here>/models/block/condensed_dirt.json`
- `assets/<mod id here>/models/item/condensed_dirt.json`

The item model is pretty simple, it can just use the block model as a parent - since most block models have support for being rendered in a GUI:

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

The block model however, in our case, must parent the `block/cube_all` model:

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

When you load into the game, you may notice that the texture is still missing. This is because you need to add a blockstate definition.

## Creating the Block State Definition

The blockstate definition is used to instruct the game on which model to render based on the current state of the block.

For the example block, which doesn't have a complex blockstate, only one entry is needed in the definition.

This file should be located in the `assets/mod_id/blockstates` folder, and its name should match the block ID used when registering your block in the `ModBlocks` class. For instance, if the block ID is `condensed_dirt`, the file should be named `condensed_dirt.json`.

@[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](/blocks/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:

![Block in world with suitable texture and model.](/assets/develop/blocks/first_block_4.png)

## Adding Block Drops

When breaking the block in survival, you may see that the block does not drop - you might want this functionality, however to make your block drop as an item on break you must implement its loot table - the loot table file should be placed in the `data/<mod id here>/loot_tables/blocks/` folder.

::: info
For a greater understanding of loot tables, you can refer to the [Minecraft Wiki - Loot Tables](https://minecraft.wiki/w/Loot_table) page.
:::

@[code](@/reference/latest/src/main/resources/data/fabric-docs-reference/loot_tables/blocks/condensed_dirt.json)

This loot table provides a single item drop of the block item when the block is broken, and when it is blown up by an explosion.

## Recommending a Harvesting Tool

You may also want your block to be harvestable only by a specific tool - for example, you may want to make your block faster to harvest with a shovel.

All the tool tags should be placed in the `data/minecraft/tags/mineable/` folder - where the name of the file depends on the type of tool used, one of the following:

- `hoe.json`
- `axe.json`
- `pickaxe.json`
- `shovel.json`

The contents of the file are quite simple - it is a list of items that should be added to the tag.

This example adds the "Condensed Dirt" block to the `shovel` tag.

@[code](@/reference/latest/src/main/resources/data/minecraft/tags/mineable/shovel.json)

## Mining Levels

Similarly, the mining level tag can be found in the same folder, and respects the following format:

- `needs_stone_tool.json` - A minimum level of stone tools
- `needs_iron_tool.json` - A minimum level of iron tools
- `needs_diamond_tool.json` - A minimum level of diamond tools.

The file has the same format as the harvesting tool file - a list of items to be added to the tag.

## 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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/develop/blocks/first_block_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.docs.block;

import net.fabricmc.api.ModInitializer;

// :::1
public class FabricDocsReferenceBlocks implements ModInitializer {
@Override
public void onInitialize() {
ModBlocks.initialize();
}
}
// :::1
Loading