From 40e3d13d06f6f2bab324b81f7620a2522269370f Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Tue, 17 Oct 2023 19:20:02 +0200 Subject: [PATCH 01/27] explain blocks and blockstates in more depth --- docs/blocks/index.md | 62 +++++++++++++++++++-------------- docs/blocks/states.md | 80 +++++++++++++++++-------------------------- 2 files changed, 67 insertions(+), 75 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index f083f104d..c6f5e39f6 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -1,51 +1,61 @@ Blocks ====== -Blocks are, obviously, essential to the Minecraft world. They make up all of the terrain, structures, and machines. Chances are if you are interested in making a mod, then you will want to add some blocks. This page will guide you through the creation of blocks, and some of the things you can do with them. +Blocks are, obviously, essential to the Minecraft world. They make up all the terrain, structures, and machines. Chances are if you are interested in making a mod, then you will want to add some blocks. This page will guide you through the creation of blocks, and some of the things you can do with them. -Creating a Block ----------------- +One block to rule them all +-------------------------- -### Basic Blocks +Before we get started, it is important to understand that there is only ever one of each block in the game. Even though you might see thousands of dirt blocks, or stone blocks, or crafting tables in the world, there is only ever one of those actually registered to the game. It is just displayed a lot of times. -For simple blocks, which need no special functionality (think cobblestone, wooden planks, etc.), a custom class is not necessary. You can create a block by instantiating the `Block` class with a `BlockBehaviour$Properties` object. This `BlockBehaviour$Properties` object can be made using `BlockBehaviour$Properties#of`, and it can be customized by calling its methods. For instance: +Due to this, a block should only ever be instantiated once, and that is during registration. Once the block is registered, you can then use the registered reference as needed. See the [registration] page for more information on how to register game objects, such as blocks. -- `strength` - The hardness controls the time it takes to break the block. It is an arbitrary value. For reference, stone has a hardness of 1.5, and dirt 0.5. If the block should be unbreakable a hardness of -1.0 should be used, see the definition of `Blocks#BEDROCK` as an example. The resistance controls the explosion resistance of the block. For reference, stone has a resistance of 6.0, and dirt 0.5. +Creating blocks +--------------- + +### Basic blocks + +For simple blocks which need no special functionality (think cobblestone, wooden planks, etc.), the `Block` class can be used directly. To do so, during registration, instantiate `Block` with a `BlockBehaviour$Properties` parameter. This `BlockBehaviour$Properties` parameter can be created using `BlockBehaviour$Properties#of`, and it can be customized by calling its methods. For instance: + +- `strength` - This method takes two parameters: the hardness and the resistance. + - The hardness is an arbitrary value that controls the time it takes to break the block. For reference, stone has a hardness of 1.5, dirt has a hardness of 0.5, obsidian has a hardness of 50, and unbreakable blocks (such as bedrock) have a hardness of -1. + - The resistance is an arbitrary value that controls the explosion resistance of the block. For reference, stone has a resistance of 6.0, dirt has a resistance of 0.5, obsidian has a resistance of 1200, and unbreakable blocks (such as bedrock) have a hardness of 3600000. - `sound` - Controls the sound the block makes when it is punched, broken, or placed. Requires a `SoundType` argument, see the [sounds] page for more details. - `lightLevel` - Controls the light emission of the block. Takes a function with a `BlockState` parameter that returns a value from zero to fifteen. -- `friction` - Controls how slippery the block is. For reference, ice has a slipperiness of 0.98. +- `friction` - Controls how slippery the block is. For reference, regular blocks have a friction of 0.6, while ice has a slipperiness of 0.98. -All these methods are *chainable* which means you can call them in series. See the `Blocks` class for examples of this. +All these methods are **chainable**, which means you can call them in series. If you want to look at examples, see the `Blocks` class. :::note -Blocks have no setter for their `CreativeModeTab`. This is handled by the [`BuildCreativeModeTabContentsEvent`][creativetabs] if the block has an associated item (e.g. `BlockItem`). Furthermore, there is no setter for translation key of the block as it is generated from the registry name via `Block#getDescriptionId`. +It is important to understand that a block in the world is not the same thing as in an inventory. What looks like a block in an inventory is actually a `BlockItem`, a special type of item that places a block when used. This also means that things like the creative tab or the max stack size are handled by the corresponding `BlockItem`. + +A `BlockItem` must be registered separately from the block, this has the reason that not every block is intended to have a corresponding item. ::: -### Advanced Blocks +### More functionality -Of course, the above only allows for extremely basic blocks. If you want to add functionality, like player interaction, a custom class is required. However, the `Block` class has many methods and unfortunately not every single one can be documented here. See the rest of the pages in this section for things you can do with blocks. +Of course, the above only allows for extremely basic blocks. If you want to add functionality, like player interaction, a custom class that extends `Block` is required. The `Block` class has many methods and unfortunately, not every single one can be documented here. Please refer to other pages in this section, or to the code of `Block`, for more information. -Registering a Block -------------------- +If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity] should be used. -Blocks must be [registered][registering] to function. +### Resources -:::caution -A block in the level and a "block" in an inventory are very different things. A block in the level is represented by an `BlockState`, and its behavior defined by an instance of `Block`. Meanwhile, an item in an inventory is an `ItemStack`, controlled by an `Item`. As a bridge between the different worlds of `Block` and `Item`, there exists the class `BlockItem`. `BlockItem` is a subclass of `Item` that has a field `block` that holds a reference to the `Block` it represents. `BlockItem` defines some of the behavior of a "block" as an item, like how a right click places the block. It's possible to have a `Block` without an `BlockItem`. (E.g. `minecraft:water` exists a block, but not an item. It is therefore impossible to hold it in an inventory as one.) +If you register your block and place it in the world, you will find it to be missing things like a texture. This is because textures, among others, are handled by Minecraft's resource system. -When a block is registered, *only* a block is registered. The block does not automatically have an `BlockItem`. To create a basic `BlockItem` for a block, one should set the registry name of the `BlockItem` to that of its `Block`. Custom subclasses of `BlockItem` may be used as well. Once an `BlockItem` has been registered for a block, `Block#asItem` can be used to retrieve it. `Block#asItem` will return `Items#AIR` if there is no `BlockItem` for the `Block`, so if you are not certain that there is an `BlockItem` for the `Block` you are using, check for if `Block#asItem` returns `Items#AIR`. -::: +To apply a simple texture to a block, you must add a blockstate JSON, a model JSON, and a texture. See the section on [resources] for more information. -#### Optionally Registering Blocks +Using blocks +------------ -In the past there have been several mods that have allowed users to disable blocks/items in a configuration file. However, you shouldn't do this. There is no limit on the amount of blocks that can be register, so register all blocks in your mod! If you want a block to be disabled through a configuration file, you should disable the crafting recipe. If you would like to disable the block in the creative tab, use a `FeatureFlag` when building the contents within [`BuildCreativeModeTabContentsEvent`][creativetabs]. +Most places where you'd expect a block actually take a `BlockState` instead. For example, `Level#setBlock` takes a `BlockState`, not a `Block`, despite the misleading name. If you have a block that does not have any blockstate properties, you just have one blockstate on that block. That one blockstate can be retrieved by calling `Block#defaultBlockState`. -Further Reading ---------------- +Similarly, most methods in `Block` that can be overridden by you have a `BlockState` as one of their parameters. This allows you to perform different behavior for different blockstates. For example, if a door is right-clicked, what happens depends on whether the door is currently open or closed. -For information about block properties, such as those used for vanilla blocks like fences, walls, and many more, see the section on [blockstates]. +For more information regarding how blocks and blockstates are used, see [Using blockstates]. -[sounds]: ../gameeffects/sounds.md -[creativetabs]: ../items/index.md#creative-tabs -[registering]: ../concepts/registries.md#methods-for-registering +[block entity]: ../blockentities/index.md [blockstates]: states.md +[registration]: ../concepts/registries.md#methods-for-registering +[resources]: ../resources/client/index.md +[sounds]: ../gameeffects/sounds.md +[Using blockstates]: states.md#using-blockstates diff --git a/docs/blocks/states.md b/docs/blocks/states.md index f18bc385e..52590b343 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -1,54 +1,32 @@ Block States ============ -Legacy Behavior ---------------------------------------- +Introduction +------------ -In Minecraft 1.7 and previous versions, blocks which need to store placement or state data that did not have BlockEntities used **metadata**. Metadata was an extra number stored with the block, allowing different rotations, facings, or even completely separate behaviors within a block. +A blockstate is a variant of a block. For example, a slab has three variants: top, bottom and double. These three variants ("states") are represented through three different blockstates. -However, the metadata system was confusing and limited, since it was stored as only a number alongside the block ID, and had no meaning except what was commented in the code. For example, to implement a block that can face a direction and be on either the upper or lower half of a block space (such as a stair): +A blockstate property is described by an instance of `Property`. For example, slabs use an `EnumProperty`. Other examples include `instrument` (`EnumProperty`), `facing` (`DirectionProperty`), or `powered` (`BooleanProperty`). Each property has the value of the type `T` parametrized by `Property`. -```java -switch (meta) { - case 0: { ... } // south and on the lower half of the block - case 1: { ... } // south on the upper side of the block - case 2: { ... } // north and on the lower half of the block - case 3: { ... } // north and on the upper half of the block - // ... etc. ... -} -``` - -Because the numbers carry no meaning by themselves, no one could know what they represent unless they had access to the source code and comments. - -Introduction of States ---------------------------------------- - -In Minecraft 1.8 and above, the metadata system, along with the block ID system, was deprecated and eventually replaced with the **block state system**. The block state system abstracts out the details of the block's properties from the other behaviors of the block. - -Each *property* of a block is described by an instance of `Property`. Examples of block properties include instruments (`EnumProperty`), facing (`DirectionProperty`), poweredness (`Property`), etc. Each property has the value of the type `T` parametrized by `Property`. +A unique pair can be constructed from the `Block` and a map of every `Property` of that block to their associated values. This unique pair is called a blockstate, represented by the `BlockState` class. As with blocks themselves, every blockstate exists exactly once in memory. -A unique pair can be constructed from the `Block` and a map of the `Property` to their associated values. This unique pair is called a `BlockState`. +The `BlockState` system is a flexible and powerful system, but it also has limitations. `BlockState`s are immutable, and all combinations of their properties are generated on startup of the game. This means that having a `BlockState` with many properties and possible values will slow down the loading of the game, take up extra RAM, and may end up making your code confusing. -The previous system of meaningless metadata values were replaced by a system of block properties, which are easier to interpret and deal with. Previously, a stone button which is facing east and is powered or held down is represented by "`minecraft:stone_button` with metadata `9`. Now, this is represented by "`minecraft:stone_button[facing=east,powered=true]`". +Immutability has its upsides as well, though. For example, `==` can and should be used when comparing `BlockState`s. Another upside is that, using `BlockState#setValue(Property)`, you can very easily go from one state to another. This does not actually create a new `BlockState`; it returns the previously generated state with that value instead. -Proper Usage of Block States ---------------------------------------- +`BlockState` is also a final class, meaning it cannot be extended. **Any functionality goes in the corresponding Block class!** -The `BlockState` system is a flexible and powerful system, but it also has limitations. `BlockState`s are immutable, and all combinations of their properties are generated on startup of the game. This means that having a `BlockState` with many properties and possible values will slow down the loading of the game, and befuddle anyone trying to make sense of your block logic. +When to use blockstates +----------------------- -Not all blocks and situations require the usage of `BlockState`; only the most basic properties of a block should be put into a `BlockState`, and any other situation is better off with having a `BlockEntity` or being a separate `Block`. Always consider if you actually need to use blockstates for your purposes. +Only the most basic properties of a block should be put into a `BlockState`, sometimes using a `BlockEntity` or multiple separate `Block`s is the better approach. Always consider if you actually need to use blockstates for your purposes. -:::note -A good rule of thumb is: **if it has a different name, it should be a separate block**. -::: +A good rule of thumb for that is: **if it has a different name, it should be a separate block**. An example is making chair blocks: the direction of the chair should be a property, while the different types of wood should be separated into different blocks. So you'd have one chair block for each wood type, and each chair block has four blockstates (one for each rotation). -An example is making chair blocks: the *direction* of the chair should be a *property*, while the different *types of wood* should be separated into different blocks. -An "Oak Chair" facing east (`oak_chair[facing=east]`) is different from a "Spruce Chair" facing west (`spruce_chair[facing=west]`). +Implementing blockstates +------------------------ -Implementing Block States ---------------------------------------- - -In your Block class, create or reference `static final` `Property` objects for every property that your Block has. You are free to make your own `Property` implementations, but the means to do that are not covered in this article. The vanilla code provides several convenience implementations: +In your block class, create or reference `static final Property` constants for every property that your block has. You are free to make your own `Property` implementations, but the means to do that are not covered in this article. The vanilla code provides several convenience implementations: * `IntegerProperty` * Implements `Property`. Defines a property that holds an integer value. @@ -66,13 +44,12 @@ In your Block class, create or reference `static final` `Property` objects fo The class `BlockStateProperties` contains shared vanilla properties which should be used or referenced whenever possible, in place of creating your own properties. -When you have your desired `Property<>` objects, override `Block#createBlockStateDefinition(StateDefinition$Builder)` in your Block class. In that method, call `StateDefinition$Builder#add(...);` with the parameters as every `Property` you wish the block to have. +When you have your desired property constants, override `Block#createBlockStateDefinition(StateDefinition$Builder)` in your block class. In that method, call `StateDefinition$Builder#add(...);` with the parameters being all the properties you wish the block to have - typically this would be all the properties you defined before. -Every block will also have a "default" state that is automatically chosen for you. You can change this "default" state by calling the `Block#registerDefaultState(BlockState)` method from your constructor. When your block is placed it will become this "default" state. An example from `DoorBlock`: +Every block will also have a default state. Usually, the default state uses the default value of every property. You can change the default state by calling the `Block#registerDefaultState(BlockState)` method from your constructor. For example, this is what the method call looks like in `DoorBlock`: ```java -this.registerDefaultState( - this.stateDefinition.any() +this.registerDefaultState(this.stateDefinition.any() .setValue(FACING, Direction.NORTH) .setValue(OPEN, false) .setValue(HINGE, DoorHingeSide.LEFT) @@ -81,16 +58,21 @@ this.registerDefaultState( ); ``` -If you wish to change what `BlockState` is used when placing your block, you can overwrite `Block#getStateForPlacement(BlockPlaceContext)`. This can be used to, for example, set the direction of your block depending on where the player is standing when they place it. +If you wish to change what `BlockState` is used when placing your block, override `Block#getStateForPlacement(BlockPlaceContext)`. This can be used to, for example, set the direction of your block depending on where the player is standing or looking when they place it. -Because `BlockState`s are immutable, and all combinations of their properties are generated on startup of the game, calling `BlockState#setValue(Property, T)` will simply go to the `Block`'s `StateHolder` and request the `BlockState` with the set of values you want. +Using blockstates +----------------- -Because all possible `BlockState`s are generated at startup, you are free and encouraged to use the reference equality operator (`==`) to check if two `BlockState`s are equal. +You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. -Using `BlockState`'s ---------------------- +If you want to get a `BlockState` with a different set of values, simply call `BlockState#setValue(Property, T)` on an existing block state with the property and its value. If you do not have a block state available, you can call `Block#defaultBlockState` and work from there. -You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. -If you want to get a `BlockState` with a different set of values, simply call `BlockState#setValue(Property, T)` with the property and its value. +To get a `BlockState` from the level, use `Level#getBlockState(BlockPos)`. + +### `Level#setBlock` + +To set a `BlockState` in the level, use `Level#setBlock(BlockPos, BlockState, int)`. + +The `int` parameter deserves some extra explanation. It denotes some options primarily related to networking. -You can get and place `BlockState`'s in the level using `Level#setBlockAndUpdate(BlockPos, BlockState)` and `Level#getBlockState(BlockPos)`. If you are placing a `Block`, call `Block#defaultBlockState()` to get the "default" state, and use subsequent calls to `BlockState#setValue(Property, T)` as stated above to achieve the desired state. +To help setting this option correctly, there are a number of constants in `Block`, prefixed with `UPDATE_`, for example `Block.UPDATE_NEIGHBORS` or `Block.UPDATE_IMMEDIATELY`. These constants can be ORed bitwise (for example `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`) if you wish to combine them. If you're unsure which one to use, use `Block.UPDATE_ALL`. From 4c87eac4dab0ae75fcda8e06ddb19125db5888a9 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Tue, 17 Oct 2023 22:27:05 +0200 Subject: [PATCH 02/27] update headers --- docs/blocks/index.md | 10 +++++----- docs/blocks/states.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index c6f5e39f6..47131a7b5 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -3,17 +3,17 @@ Blocks Blocks are, obviously, essential to the Minecraft world. They make up all the terrain, structures, and machines. Chances are if you are interested in making a mod, then you will want to add some blocks. This page will guide you through the creation of blocks, and some of the things you can do with them. -One block to rule them all +One Block to Rule Them All -------------------------- Before we get started, it is important to understand that there is only ever one of each block in the game. Even though you might see thousands of dirt blocks, or stone blocks, or crafting tables in the world, there is only ever one of those actually registered to the game. It is just displayed a lot of times. Due to this, a block should only ever be instantiated once, and that is during registration. Once the block is registered, you can then use the registered reference as needed. See the [registration] page for more information on how to register game objects, such as blocks. -Creating blocks +Creating Blocks --------------- -### Basic blocks +### Basic Blocks For simple blocks which need no special functionality (think cobblestone, wooden planks, etc.), the `Block` class can be used directly. To do so, during registration, instantiate `Block` with a `BlockBehaviour$Properties` parameter. This `BlockBehaviour$Properties` parameter can be created using `BlockBehaviour$Properties#of`, and it can be customized by calling its methods. For instance: @@ -32,7 +32,7 @@ It is important to understand that a block in the world is not the same thing as A `BlockItem` must be registered separately from the block, this has the reason that not every block is intended to have a corresponding item. ::: -### More functionality +### More Functionality Of course, the above only allows for extremely basic blocks. If you want to add functionality, like player interaction, a custom class that extends `Block` is required. The `Block` class has many methods and unfortunately, not every single one can be documented here. Please refer to other pages in this section, or to the code of `Block`, for more information. @@ -44,7 +44,7 @@ If you register your block and place it in the world, you will find it to be mis To apply a simple texture to a block, you must add a blockstate JSON, a model JSON, and a texture. See the section on [resources] for more information. -Using blocks +Using Blocks ------------ Most places where you'd expect a block actually take a `BlockState` instead. For example, `Level#setBlock` takes a `BlockState`, not a `Block`, despite the misleading name. If you have a block that does not have any blockstate properties, you just have one blockstate on that block. That one blockstate can be retrieved by calling `Block#defaultBlockState`. diff --git a/docs/blocks/states.md b/docs/blocks/states.md index 52590b343..77426754b 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -1,5 +1,5 @@ -Block States -============ +Blockstates +=========== Introduction ------------ @@ -16,14 +16,14 @@ Immutability has its upsides as well, though. For example, `==` can and should b `BlockState` is also a final class, meaning it cannot be extended. **Any functionality goes in the corresponding Block class!** -When to use blockstates +When to Use Blockstates ----------------------- Only the most basic properties of a block should be put into a `BlockState`, sometimes using a `BlockEntity` or multiple separate `Block`s is the better approach. Always consider if you actually need to use blockstates for your purposes. A good rule of thumb for that is: **if it has a different name, it should be a separate block**. An example is making chair blocks: the direction of the chair should be a property, while the different types of wood should be separated into different blocks. So you'd have one chair block for each wood type, and each chair block has four blockstates (one for each rotation). -Implementing blockstates +Implementing Blockstates ------------------------ In your block class, create or reference `static final Property` constants for every property that your block has. You are free to make your own `Property` implementations, but the means to do that are not covered in this article. The vanilla code provides several convenience implementations: @@ -60,7 +60,7 @@ this.registerDefaultState(this.stateDefinition.any() If you wish to change what `BlockState` is used when placing your block, override `Block#getStateForPlacement(BlockPlaceContext)`. This can be used to, for example, set the direction of your block depending on where the player is standing or looking when they place it. -Using blockstates +Using Blockstates ----------------- You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. From b81bf08a75ecb2fc4bc7ff54285708f2fd5287ab Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Wed, 18 Oct 2023 01:38:41 +0200 Subject: [PATCH 03/27] implement feedback, add reference.md --- docs/blocks/index.md | 66 +++++++++++++++++-------- docs/blocks/reference.md | 95 ++++++++++++++++++++++++++++++++++++ docs/blocks/states.md | 103 ++++++++++++++++++++++++++++----------- 3 files changed, 215 insertions(+), 49 deletions(-) create mode 100644 docs/blocks/reference.md diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 47131a7b5..5e4a1503f 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -6,56 +6,80 @@ Blocks are, obviously, essential to the Minecraft world. They make up all the te One Block to Rule Them All -------------------------- -Before we get started, it is important to understand that there is only ever one of each block in the game. Even though you might see thousands of dirt blocks, or stone blocks, or crafting tables in the world, there is only ever one of those actually registered to the game. It is just displayed a lot of times. +Before we get started, it is important to understand that there is only ever one of each block in the game. A world consists of thousands of references to that one block in different locations. In other words, the same block is just displayed a lot of times. -Due to this, a block should only ever be instantiated once, and that is during registration. Once the block is registered, you can then use the registered reference as needed. See the [registration] page for more information on how to register game objects, such as blocks. +Due to this, a block should only ever be instantiated once, and that is during registration. Once the block is registered, you can then use the registered reference as needed. Consider this example (see the [Registration][registration] page if you do not know what you are looking at): + +```java +public static final RegistryObject MY_BLOCK = BLOCKS.register("my_block", () -> new Block(...)); +``` + +After registering the block, all references to the new `my_block` should use this constant. For example, if you want to check if the block at a given position is a `my_block`, the code for that would look something like this: + +```java +level.getBlockState(position).is(MyBlockRegistrationClass.MY_BLOCK.get()); +``` + +:::danger +As soon as you create a `new Block()` outside registration, things can and will break! +::: Creating Blocks --------------- ### Basic Blocks -For simple blocks which need no special functionality (think cobblestone, wooden planks, etc.), the `Block` class can be used directly. To do so, during registration, instantiate `Block` with a `BlockBehaviour$Properties` parameter. This `BlockBehaviour$Properties` parameter can be created using `BlockBehaviour$Properties#of`, and it can be customized by calling its methods. For instance: +For simple blocks which need no special functionality (think cobblestone, wooden planks, etc.), the `Block` class can be used directly. To do so, during registration, instantiate `Block` with a `BlockBehaviour.Properties` parameter. This `BlockBehaviour.Properties` parameter can be created using `BlockBehaviour.Properties#of`, and it can be customized by calling its methods. The most important methods for this are: + +- `destroyTime` - Determines the time the block needs to be destroyed. +- `explosionResistance` - Determines the explosion resistance of the block. +- `sound` - Sets the sound the block makes when it is punched, broken, or placed. +- `lightLevel` - Sets the light emission of the block. Accepts a function with a `BlockState` parameter that returns a value between 0 and 15. +- `friction` - Sets the friction (slipperiness) of the block. -- `strength` - This method takes two parameters: the hardness and the resistance. - - The hardness is an arbitrary value that controls the time it takes to break the block. For reference, stone has a hardness of 1.5, dirt has a hardness of 0.5, obsidian has a hardness of 50, and unbreakable blocks (such as bedrock) have a hardness of -1. - - The resistance is an arbitrary value that controls the explosion resistance of the block. For reference, stone has a resistance of 6.0, dirt has a resistance of 0.5, obsidian has a resistance of 1200, and unbreakable blocks (such as bedrock) have a hardness of 3600000. -- `sound` - Controls the sound the block makes when it is punched, broken, or placed. Requires a `SoundType` argument, see the [sounds] page for more details. -- `lightLevel` - Controls the light emission of the block. Takes a function with a `BlockState` parameter that returns a value from zero to fifteen. -- `friction` - Controls how slippery the block is. For reference, regular blocks have a friction of 0.6, while ice has a slipperiness of 0.98. +So for example, a simple implementation would look something like this: -All these methods are **chainable**, which means you can call them in series. If you want to look at examples, see the `Blocks` class. +```java +public static final RegistryObject MY_BETTER_BLOCK = BLOCKS.register("my_better_block", () -> new Block(BlockBehaviour.Properties.of() + .destroyTime(2.0f) + .explosionResistance(10.0f) + .sound(SoundType.GRAVEL) + .lightLevel(state -> 7))); +``` + +For further documentation, see the [`BlockBehaviour.Properties` reference][reference_properties]. For more examples, or to look at the values used by Minecraft, have a look at the `Blocks` class. :::note -It is important to understand that a block in the world is not the same thing as in an inventory. What looks like a block in an inventory is actually a `BlockItem`, a special type of item that places a block when used. This also means that things like the creative tab or the max stack size are handled by the corresponding `BlockItem`. +It is important to understand that a block in the world is not the same thing as in an inventory. What looks like a block in an inventory is actually a `BlockItem`, a special type of [item] that places a block when used. This also means that things like the creative tab or the max stack size are handled by the corresponding `BlockItem`. -A `BlockItem` must be registered separately from the block, this has the reason that not every block is intended to have a corresponding item. +A `BlockItem` must be registered separately from the block. This is because a block does not necessarily need an item, for example if it is not meant to be collected (as is the case with fire, for example). ::: ### More Functionality -Of course, the above only allows for extremely basic blocks. If you want to add functionality, like player interaction, a custom class that extends `Block` is required. The `Block` class has many methods and unfortunately, not every single one can be documented here. Please refer to other pages in this section, or to the code of `Block`, for more information. +Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a non-1x1x1 hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; these are documented in the [`Block` reference][reference_block]. -If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity] should be used. +If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity][blockentities] should be used. The rule of thumb here is that if you have a finite amount of states, use blockstates, and if you have an infinite or near-infinite amount of states, use a block entity. ### Resources If you register your block and place it in the world, you will find it to be missing things like a texture. This is because textures, among others, are handled by Minecraft's resource system. -To apply a simple texture to a block, you must add a blockstate JSON, a model JSON, and a texture. See the section on [resources] for more information. +To apply a simple texture to a block, you must add a blockstate JSON, a model JSON, and a texture PNG. See the section on [resources] for more information. Using Blocks ------------ -Most places where you'd expect a block actually take a `BlockState` instead. For example, `Level#setBlock` takes a `BlockState`, not a `Block`, despite the misleading name. If you have a block that does not have any blockstate properties, you just have one blockstate on that block. That one blockstate can be retrieved by calling `Block#defaultBlockState`. - -Similarly, most methods in `Block` that can be overridden by you have a `BlockState` as one of their parameters. This allows you to perform different behavior for different blockstates. For example, if a door is right-clicked, what happens depends on whether the door is currently open or closed. +Blocks are very rarely directly used to do things. The main purpose of a block class is to define behavior of a block. The game then runs that behavior through `BlockState`s, often passing them into the `Block`'s functionality methods as a parameter. -For more information regarding how blocks and blockstates are used, see [Using blockstates]. +For more information on how blockstates are used, see [Using Blockstates][usingblockstates]. -[block entity]: ../blockentities/index.md +[blockentities]: ../blockentities/index.md [blockstates]: states.md +[item]: ../items/index.md +[reference_properties]: reference.md#blockbehaviourproperties +[reference_block]: reference.md#block [registration]: ../concepts/registries.md#methods-for-registering [resources]: ../resources/client/index.md [sounds]: ../gameeffects/sounds.md -[Using blockstates]: states.md#using-blockstates +[usingblockstates]: states.md#using-blockstates diff --git a/docs/blocks/reference.md b/docs/blocks/reference.md new file mode 100644 index 000000000..851ca52d8 --- /dev/null +++ b/docs/blocks/reference.md @@ -0,0 +1,95 @@ +Method Reference +================ + +This article is a reference for all protected or public methods in various block-related classes. + +`Block` +------- + +:::note +Some of these methods are actually located in `BlockBehaviour`, the abstract superclass of `Block`, or in `IForgeBlock`, a NeoForge-added interface implemented by `Block` that adds extra utilities for modders to the `Block` class. However, for all our intents and purposes, we can treat them as if they were located in `Block` itself. +::: + +| Method | Description | +|--------|----------------------| +| `test` | This is a test entry | +| `todo` | More work is needed | + +//TODO + +`BlockState` +------------ + +:::note +Some of these methods are actually located in `BlockBehaviour.BlockStateBase`, the abstract superclass of `BlockState`, or in `IForgeBlockState`, a NeoForge-added interface implemented by `Block` that adds extra utilities for modders to the `BlockState` class. However, for all our intents and purposes, we can treat them as if they were located in `Block` itself. +::: + +| Method | Description | +|--------|----------------------| +| `test` | This is a test entry | +| `todo` | More work is needed | + +`BlockBehaviour.Properties` +--------------------------- + +### Static methods + +| Method | Description | +|-------------------------------------------------|---------------------------------------------------------------------------------------| +| `public static Properties of()` | Returns a new `Properties` object with default values. | +| `public static Properties copy(BlockBehaviour)` | Returns a new `Properties` object with the values used by the given `BlockBehaviour`. | + +### Instance methods + +All instance methods of `Properties` are `public` and return themselves (`return this;`). As a result, all the below methods can be chained at will; that is, appended in whatever order you like. An example from the `Blocks` class best shows this: +```java +public static final Block OAK_PLANKS = register("oak_planks", new Block(BlockBehaviour.Properties.of() + .mapColor(MapColor.WOOD) + .instrument(NoteBlockInstrument.BASS) + .strength(2.0F, 3.0F) + .sound(SoundType.WOOD) + .ignitedByLava() +)); +``` + +| Method | Description | +|-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `air()` | Tells the game to consider the block as air. | +| `destroyTime(float)` | Sets the block's destroy time. Default value is 0. Typical values include 1.5 for stone, 0.5 for dirt, 50 for obsidian, and -1 for unbreakable blocks such as bedrock. | +| `explosionResistance(float)` | Sets the block's explosion resistance. Default value is 0. Typical values include 6 for stone, 0.5 for dirt, 1200 for obsidian, and 3600000 for unbreakable blocks such as bedrock. | +| `strength(float, float)` | Sets the block's destroy time (first parameter) and explosion resistance (second parameter). Equivalent to calling `.destroyTime(float).explosionResistance(float)` with the same parameters. | +| `strength(float)` | Sets the block's destroy time and explosion resistance. Equivalent to calling `.destroyTime(float).explosionResistance(float)` with the same parameter. | +| `instabreak()` | Sets the block's destroy time and explosion resistance to 0. Equivalent to calling `.destroyTime(0).explosionResistance(0)`. | +| `requiresCorrectToolForDrops()` | Sets the block to require the correct tool in order to drop anything. If false, the correct tool will mine faster, but items will drop regardless of what tool was used. `true` for blocks like stone or the various ores, `false` for blocks like planks or dirt. | +| `noLootTable()` | Sets the block to not use a loot table, causing the block to not drop anything. Note that no drops can also be achieved by using an empty loot table instead of no loot table at all, so only use this where applicable. Vanilla uses include unobtainable blocks (bedrock, barriers, etc.) and fluids (water/lava blocks). | +| `dropsLike(Block)` | **DEPRECATED: Use `lootFrom` instead!** Sets the block to use the given block's loot table instead of its own. | +| `lootFrom(Supplier)` | Sets the block to use the given block's loot table instead of its own. Uses a `Supplier` to allow directly passing in `RegistryObject`s. | +| `noParticlesOnBreak()` | Disables breaking particles for the block. | +| `replaceable()` | Enables the block to be replaceable by other blocks. This is relevant when trying to place a block into another blocks. For example, grass is replaceable, while flowers are not. | +| `friction(float)` | Sets the block's friction (slipperiness) value. Default friction value is 0.6, Ice, Packed Ice and Frosted Ice use 0.98, Blue Ice uses 0.989, and Slime Blocks use 0.8. | +| `speedFactor(float)` | Sets the block's speed factor. Entities that walk over the block will be slowed (if < 1) or sped up (if > 1) by this value. Default speed factor is 1, Soul Sand and Honey Blocks use 0.4. | +| `jumpFactor(float)` | Sets the block's jump factor. Entities that jump while standing on this block will have their jump height multiplied with this value. Default jump factor is 1, Honey Blocks use 0.5. | +| `sound(SoundType)` | Sets the block's sound type. The sound type is used when placing, mining or breaking a block. For information on how to get a `SoundType`, please refer to the [Sounds][sounds] section. | +| `lightLevel(ToIntFunction)` | Sets the block's light level, depending on the blockstate. This is a function to account for blocks like redstone lamps that have a `lit` property. The function must always return a value between 0 and 15 (both inclusive). | +| `mapColor(MapColor)` | Sets the block's map color to the given map color. | +| `mapColor(DyeColor)` | Overload of `mapColor` that accepts a `DyeColor`. The `DyeColor` is converted to its corresponding `MapColor` internally. | +| `mapColor(Function)` | Overload of `mapColor` that allows for blockstate-specific `MapColor`s. Used for example by beds, where the head part always uses `MapColor.WOOL`, while the foot part uses the bed's color. | +| `instrument(NoteBlockInstrument)` | Sets the block's note block instrument. The instrument is used for a note block placed above the block. A list of valid options can be found in the source code for `NoteBlockInstrument`. | +| `pushReaction(PushReaction)` | Sets the block's push reaction. Valid values for entities are `NORMAL` (push and pull), `DESTROY` (destroy when trying to push), `BLOCK` (block against pushing, cannot be pulled; used by hard blocks such as obsidian, as well as blocks that have an inventory), `IGNORE` (used for entites that can't be pushed/pulled, not to be used for blocks) and `PUSH_ONLY` (push, but not pull; used by Glazed Terracotta) | +| `ignitedByLava()` | Enables the block to be ignited when next to lava. Primarily used for wooden blocks. | +| `randomTicks()` | Enables random ticking for the block. Every tick, a set amount of blocks are selected in each chunk to be randomly ticked. The amount is determined by the `randomTickSpeed` gamerule (default is 3). If a block is selected and random ticking is enabled, then `Block#randomTick` is called for that block. | +| `noOcclusion()` | Disables occlusion for the block. | +| `noCollission()` | Disables collision **and occlusion** for the block. | +| `dynamicShape()` | Tells the game that the block has a dynamic shape. Used by vanilla in a few cases, such as piston heads or shulker boxes. | +| `forceSolidOn()` | ??? | +| `forceSolidOff()` | ??? | +| `isValidSpawn(StateArgumentPredicate>)` | Sets the block to be a valid spawn for entities that fulfill the given state predicate. | +| `isRedstoneConductor(StatePredicate)` | Sets the block to be a redstone conductor if the given state predicate is fulfilled. | +| `isSuffocating(StatePredicate)` | Sets the block to suffocate entities inside it if the given state predicate is fulfilled. | +| `isViewBlocking(StatePredicate)` | Sets the block to block the view for entities inside it if the given state predicate is fulfilled. Typically used with a predicate that is always `false`, for example by Glass. | +| `hasPostProcess(StatePredicate)` | Sets the block to have worldgen post processing if the given state predicate is fulfilled. Always true for Brown Mushrooms, Red Mushrooms and Magma Blocks. | +| `emissiveRendering(StatePredicate)` | Sets the block to have emissive rendering if the given state predicate is fulfilled. True for Magma Blocks and activated Sculk Sensors. | +| `offsetType(OffsetType)` | Sets the block's random position offset type. The random position offset slightly offsets a block's hitbox and model position to make it feel more natural. Has three possible values: `NONE` (default), `XZ` (horizontal) and `XYZ` (all directions). Grass and Ferns use `XYZ`, while many flowers and flower-like blocks use `XZ`. | +| `requiredFeatures(FeatureFlag...)` | Sets the block's required feature flags. The block will only be actually registered if all the passed feature flags are activated. Currently unused, but historically used for bamboo and cherry wood (among others) when they were in their experimental phase. | + +[sounds]: ../gameeffects/sounds.md diff --git a/docs/blocks/states.md b/docs/blocks/states.md index 77426754b..5f23b37bc 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -4,32 +4,53 @@ Blockstates Introduction ------------ -A blockstate is a variant of a block. For example, a slab has three variants: top, bottom and double. These three variants ("states") are represented through three different blockstates. +Often, you will find yourself in a situation where you want different states of a block. For example, a wheat crop has eight growth stages, and making a separate block for each stage feels wrong. Or you have a slab or slab-like block - one bottom state, one top state, and one state that has both. -A blockstate property is described by an instance of `Property`. For example, slabs use an `EnumProperty`. Other examples include `instrument` (`EnumProperty`), `facing` (`DirectionProperty`), or `powered` (`BooleanProperty`). Each property has the value of the type `T` parametrized by `Property`. +This is where blockstates come into play. Blockstates are an easy way to represent the different states a block can have, like a growth stage or a slab placement type. -A unique pair can be constructed from the `Block` and a map of every `Property` of that block to their associated values. This unique pair is called a blockstate, represented by the `BlockState` class. As with blocks themselves, every blockstate exists exactly once in memory. +Blockstates use a system of properties. A block can have multiple properties of multiple types. For example, a lever has two properties: whether it is currently activated (`powered`, 2 options) and which direction it is placed in (`facing`, 6 options). So in total, the lever has 12 different blockstates: -The `BlockState` system is a flexible and powerful system, but it also has limitations. `BlockState`s are immutable, and all combinations of their properties are generated on startup of the game. This means that having a `BlockState` with many properties and possible values will slow down the loading of the game, take up extra RAM, and may end up making your code confusing. +``` +minecraft:lever[facing=north,powered=false] +minecraft:lever[facing=east,powered=false] +minecraft:lever[facing=south,powered=false] +minecraft:lever[facing=west,powered=false] +minecraft:lever[facing=up,powered=false] +minecraft:lever[facing=down,powered=false] +minecraft:lever[facing=north,powered=true] +minecraft:lever[facing=east,powered=true] +minecraft:lever[facing=south,powered=true] +minecraft:lever[facing=west,powered=true] +minecraft:lever[facing=up,powered=true] +minecraft:lever[facing=down,powered=true] +``` + +The notation `blockid[property1=value1,property2=value,...]` is the standardized way of representing a blockstate in text form, and is used in some locations in vanilla, for example in commmands. -Immutability has its upsides as well, though. For example, `==` can and should be used when comparing `BlockState`s. Another upside is that, using `BlockState#setValue(Property)`, you can very easily go from one state to another. This does not actually create a new `BlockState`; it returns the previously generated state with that value instead. +If your block does not have any blockstate properties defined, it still has exactly one blockstate - that is the one without any properties, since there are no properties to specify. This can be denoted as `minecraft:oak_planks[]` or simply `minecraft:oak_planks`. -`BlockState` is also a final class, meaning it cannot be extended. **Any functionality goes in the corresponding Block class!** +As with blocks, every `BlockState` exists exactly once in memory. This has the convenient side effect that `==` can and should be used to compare `BlockState`s. `BlockState` is also a final class, meaning it cannot be extended. **Any functionality goes in the corresponding [Block][block] class!** When to Use Blockstates ----------------------- -Only the most basic properties of a block should be put into a `BlockState`, sometimes using a `BlockEntity` or multiple separate `Block`s is the better approach. Always consider if you actually need to use blockstates for your purposes. +### Blockstates vs. Separate Blocks + +A good rule of thumb is: **if it has a different name, it should be a separate block**. An example is making chair blocks: the direction of the chair should be a property, while the different types of wood should be separated into different blocks. So you'd have one chair block for each wood type, and each chair block has four blockstates (one for each direction). + +### Blockstates vs. [Block Entities][blockentity] + +Here, the rule of thumb is: **if you have a finite amount of states, use a blockstate, if you have an infinite or near-infinite amount of states, use a block entity.** Block entities can store arbitrary amounts of data, but are slower than blockstates. -A good rule of thumb for that is: **if it has a different name, it should be a separate block**. An example is making chair blocks: the direction of the chair should be a property, while the different types of wood should be separated into different blocks. So you'd have one chair block for each wood type, and each chair block has four blockstates (one for each rotation). +Blockstates and block entities can be used in conjunction with one another. For example, the chest uses blockstate properties for things like the direction, whether it is opened or not, or becoming a double chest is handled by blockstate properties, while storing the inventory or interacting with hoppers is handled by a block entity. Implementing Blockstates ------------------------ -In your block class, create or reference `static final Property` constants for every property that your block has. You are free to make your own `Property` implementations, but the means to do that are not covered in this article. The vanilla code provides several convenience implementations: +To implement a blockstate property, in your block class, create or reference a `public static final Property` constant. While you are free to make your own `Property` implementations, the vanilla code provides several convenience implementations that should cover most usecases: * `IntegerProperty` - * Implements `Property`. Defines a property that holds an integer value. + * Implements `Property`. Defines a property that holds an integer value. Note that negative values are not supported. * Created by calling `IntegerProperty#create(String propertyName, int minimum, int maximum)`. * `BooleanProperty` * Implements `Property`. Defines a property that holds a `true` or `false` value. @@ -37,35 +58,58 @@ In your block class, create or reference `static final Property` constants fo * `EnumProperty>` * Implements `Property`. Defines a property that can take on the values of an Enum class. * Created by calling `EnumProperty#create(String propertyName, Class enumClass)`. - * It is also possible to use only a subset of the Enum values (e.g. 4 out of 16 `DyeColor`s). See the overloads of `EnumProperty#create`. + * It is also possible to use only a subset of the Enum values (e.g. 4 out of 16 `DyeColor`s), see the overloads of `EnumProperty#create`. * `DirectionProperty` - * This is a convenience implementation of `EnumProperty` - * Several convenience predicates are also provided. For example, to get a property that represents the cardinal directions, call `DirectionProperty.create("", Direction.Plane.HORIZONTAL)`; to get the X directions, `DirectionProperty.create("", Direction.Axis.X)`. + * Extends `EnumProperty`. Defines a property that can take on a `Direction`. + * Created by calling `DirectionProperty#create(String propertyName)`. + * Several convenience predicates are provided. For example, to get a property that represents the cardinal directions, call `DirectionProperty.create("", Direction.Plane.HORIZONTAL)`; to get the X directions, `DirectionProperty.create("", Direction.Axis.X)`. The class `BlockStateProperties` contains shared vanilla properties which should be used or referenced whenever possible, in place of creating your own properties. -When you have your desired property constants, override `Block#createBlockStateDefinition(StateDefinition$Builder)` in your block class. In that method, call `StateDefinition$Builder#add(...);` with the parameters being all the properties you wish the block to have - typically this would be all the properties you defined before. +Once you have your property constant, override `Block#createBlockStateDefinition(StateDefinition$Builder)` in your block class. In that method, call `StateDefinition.Builder#add(YOUR_PROPERTY);`. `StateDefinition.Builder#add` has a vararg parameter, so if you have multiple properties, you can add them all in one go. -Every block will also have a default state. Usually, the default state uses the default value of every property. You can change the default state by calling the `Block#registerDefaultState(BlockState)` method from your constructor. For example, this is what the method call looks like in `DoorBlock`: +Every block will also have a default state. If nothing else is specified, the default state uses the default value of every property. You can change the default state by calling the `Block#registerDefaultState(BlockState)` method from your constructor. + +If you wish to change which `BlockState` is used when placing your block, override `Block#getStateForPlacement(BlockPlaceContext)`. This can be used to, for example, set the direction of your block depending on where the player is standing or looking when they place it. + +To further illustrate this, this is what the relevant bits of the `LeverBlock` class look like: ```java -this.registerDefaultState(this.stateDefinition.any() - .setValue(FACING, Direction.NORTH) - .setValue(OPEN, false) - .setValue(HINGE, DoorHingeSide.LEFT) - .setValue(POWERED, false) - .setValue(HALF, DoubleBlockHalf.LOWER) -); +public class LeverBlock extends Block { + public static final DirectionProperty FACING = BlockStateProperties.FACING; + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + public LeverBlock(BlockBehaviour.Properties pProperties) { + super(pProperties); + registerDefaultState(stateDefinition.any() // stateDefinition.any() returns a random BlockState from an internal set, we don't care because we're setting all values ourselves anyway + .setValue(FACING, Direction.NORTH) + .setValue(POWERED, false) + ); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder pBuilder) { + pBuilder.add(FACING, POWERED); + } + + @Override + @Nullable + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + // code that determines which state will be used when placing down this block, depending on the BlockPlaceContext + } +} ``` -If you wish to change what `BlockState` is used when placing your block, override `Block#getStateForPlacement(BlockPlaceContext)`. This can be used to, for example, set the direction of your block depending on where the player is standing or looking when they place it. - Using Blockstates ----------------- -You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. +You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. Reusing our lever example, this would look something like `Direction direction = leverBlockState.getValue(LeverBlock.FACING);` -If you want to get a `BlockState` with a different set of values, simply call `BlockState#setValue(Property, T)` on an existing block state with the property and its value. If you do not have a block state available, you can call `Block#defaultBlockState` and work from there. +If you want to get a `BlockState` with a different set of values, simply call `BlockState#setValue(Property, T)` on an existing block state with the property and its value. With our lever, this goes something like `leverBlockState = leverBlockState.setValue(LeverBlock.FACING, Direction.SOUTH);` + +:::note +`BlockState`s are immutable. This means that when you call `#setValue(Property, T)`, you are not actually modifying the blockstate. Instead, a lookup is performed internally, and you are given the blockstate object you requested, which is the one and only object that exists with these exact property values. This also means that just calling `state#setValue` without saving it into a variable (for example back into `state`) does nothing. +::: To get a `BlockState` from the level, use `Level#getBlockState(BlockPos)`. @@ -73,6 +117,9 @@ To get a `BlockState` from the level, use `Level#getBlockState(BlockPos)`. To set a `BlockState` in the level, use `Level#setBlock(BlockPos, BlockState, int)`. -The `int` parameter deserves some extra explanation. It denotes some options primarily related to networking. +The `int` parameter deserves some extra explanation, as its meaning is not immediately obvious. It denotes what is known as update flags. + +To help setting the update flags correctly, there are a number of `int` constants in `Block`, prefixed with `UPDATE_`. Examples include `Block.UPDATE_NEIGHBORS` or `Block.UPDATE_CLIENTS`. These constants can be added together (for example `Block.UPDATE_NEIGHBORS + Block.UPDATE_CLIENTS`) if you wish to combine them. If you're unsure which one to use, use `Block.UPDATE_ALL`. -To help setting this option correctly, there are a number of constants in `Block`, prefixed with `UPDATE_`, for example `Block.UPDATE_NEIGHBORS` or `Block.UPDATE_IMMEDIATELY`. These constants can be ORed bitwise (for example `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`) if you wish to combine them. If you're unsure which one to use, use `Block.UPDATE_ALL`. +[block]: index.md +[blockentity]: ../blockentities/index.md From 4326538ec9aa45260593de73ac7c44f5054cbb6a Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Wed, 18 Oct 2023 12:18:27 +0200 Subject: [PATCH 04/27] add reference for methods in Block.java --- docs/blocks/reference.md | 84 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/docs/blocks/reference.md b/docs/blocks/reference.md index 851ca52d8..dc4fcae7f 100644 --- a/docs/blocks/reference.md +++ b/docs/blocks/reference.md @@ -10,18 +10,88 @@ This article is a reference for all protected or public methods in various block Some of these methods are actually located in `BlockBehaviour`, the abstract superclass of `Block`, or in `IForgeBlock`, a NeoForge-added interface implemented by `Block` that adds extra utilities for modders to the `Block` class. However, for all our intents and purposes, we can treat them as if they were located in `Block` itself. ::: -| Method | Description | -|--------|----------------------| -| `test` | This is a test entry | -| `todo` | More work is needed | +### Static methods + +| Method | Description | +|---------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `public static Block byItem(@Nullable Item)` | If the given item is a `BlockItem`, that `BlockItem`'s block is returned. Otherwise, `Blocks.AIR` is returned. | +| `public static VoxelShape box(double, double, double, double, double, double)` | Creates a `VoxelShape` with the given corner points. Parameter order is x1, y1, z1, x2, y2, z2. The unit used is single pixels, or in other words, 1 / 16 of a block. So for example, if you want a shape that is exactly one pixel tall, you'd use `box(0, 0, 0, 16, 1, 16);`. | +| `public static BlockState updateOrDestroy(BlockState, BlockState, LevelAccessor, BlockPos, int, int)` | Replaces the old blockstate (first parameter) with the new blockstate (second parameter) in the given level at the given position. The first `int` parameter is the update flags (see [Using Level#setBlock][setblock] for more information). The second `int` parameter is the amount of leftover worldgen recursions. It is recommended to use the overload that omits this parameter if you are not doing worldgen. | +| `public static BlockState updateOrDestroy(BlockState, BlockState, LevelAccessor, BlockPos, int)` | Overload of `updateOrDestroy(BlockState, BlockState, LevelAccessor, BlockPos, int, int)` that uses the default recursion amount of 512 as the second int parameter. | +| `public static BlockState pushEntitiesUp(BlockState, BlockState, LevelAccessor, BlockPos)` | Helper method that pushes entities out of the second `BlockState`'s bounds (if it is greater than the first `BlockState`'s bounds). Used in scenarios such as when farmland turns back into dirt and consequently has its shape increased back to a full block. | +| `public static BlockState updateFromNeighbourShapes(BlockState, LevelAccessor, BlockPos)` | With the provided `BlockState`, performs neighbor checks for all neighboring blocks in the given level at the given position. Used for example by Endermen when they place down a block they are holding. | +| `public static boolean isExceptionForConnection(BlockState)` | Whether the given state is an exception for connection by fences, walls and iron bars. If `true`, these blocks will not connect with the given state, even if they would connect otherwise. `true` for all types of Leaves, all types of Shulker Boxes, Barriers, Carved Pumpkins, Jack o'Lanterns, Melons and Pumpkins. | +| `public static boolean shouldRenderFace(BlockState, BlockGetter, BlockPos, Direction, BlockPos)` | Calculates whether the given blockstate's face in the given direction should be rendered or not. | +| `public static boolean canSupportRigidBlocks(BlockGetter, BlockPos)` | Whether the state at the given position in the given level can support a rigid block or not. Rigid blocks are blocks like rails or pressure plates that require only a solid top face to be placed, so using this method means that they can also be placed on non-full blocks that have a full solid top face, for example a top slab. | +| `public static boolean canSupportCenter(BlockGetter, BlockPos, Direction)` | Whether the state at the given position in the given level can support a center block in the given direction or not. Center blocks are blocks that require a solid center, but can be placed on blocks that do not have a full face in that direction. Prime examples would be a torch or a candle placed on a fence, or a lantern or a bell placed on the bottom face of a fence. | +| `public static int getId(@Nullable BlockState)` | Returns the numerical ID of a blockstate by performing a lookup in the blockstate registry. The parameter may be `null`, in which case 0 is returned. Used for networking. | +| `public static BlockState stateById(int)` | Counterpart of `getId`, returns the blockstate associated with the given integer by performing a lookup in the blockstate registry. If the given integer does not correspond to a blockstate, `Blocks.AIR.defaultBlockState()` is returned instead. Used for networking. | +| `public static boolean isFaceFull(VoxelShape, Direction)` | Whether the given shape is a full shape in the given direction or not. | +| `public static boolean isShapeFullBlock(VoxelShape)` | Whether the given shape is a full 1x1x1 block shape or not. | +| `public static List getDrops(BlockState, ServerLevel, BlockPos, @Nullable BlockEntity)` | Rolls the loot table for the given blockstate and returns the results as a `List`. Includes the position context, the block entity context if the block entity parameter is not `null`, and an empty tool context when rolling the loot table. | +| `public static List getDrops(BlockState, ServerLevel, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack)` | Alternative variant of `getDrops(BlockState, ServerLevel, BlockPos, @Nullable BlockEntity)` that additionally includes entity context if the entity is not `null`, and tool context using the given `ItemStack` when rolling the loot table. | +| `public static void dropResources(BlockState, Level, BlockPos, @Nullable BlockEntity)` | Generates drops by calling `getDrops(BlockState, ServerLevel, BlockPos, @Nullable BlockEntity)` and drops them in the level as item entities. Also calls `BlockState#spawnAfterBreak(ServerLevel, BlockPos, ItemStack, boolean)` with `ItemStack.EMPTY` and `true` for the last two parameters. | +| `public static void dropResources(BlockState, Level, BlockPos)` | Alternative variant of `dropResources(BlockState, Level, BlockPos)` that omits the block entity parameter. Equivalent to calling `dropResources(BlockState, Level, BlockPos, null)` with the same first three parameters. | +| `public static void dropResources(BlockState, Level, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack, boolean)` | Generates drops by calling `getDrops(BlockState, ServerLevel, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack)` and drops them in the level as item entities. Also calls `BlockState#spawnAfterBreak(ServerLevel, BlockPos, ItemStack, boolean)` with the corresponding parameters of this method. | +| `public static void dropResources(BlockState, Level, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack)` | Alternative variant of `dropResources(BlockState, Level, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack, boolean)` that omits the boolean parameter. Equivalent to calling `dropResources(BlockState, Level, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack, true)` with the same first six parameters. | +| `public static void popResource(Level, BlockPos, ItemStack)` | Drops the given `ItemStack` into the given level at the given position, respecting the `doTileDrops` gamerule. | +| `public static void popResource(Level, BlockPos, Direction, ItemStack)` | Drops the given `ItemStack` into the given level at the given position, "popping off" the given direction and respecting the `doTileDrops` gamerule. | + +### Instance methods + +:::note +For methods with a `BlockState` parameter, it can be generally assumed that the given blockstate is a state of this block (unless stated otherwise). +::: -//TODO +| Method | Description | +|---------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `protected void createBlockStateDefinition(StateDefinition.Builder)` | Defines the block state properties this block has. See [Implementing Blockstates][implementingblockstates] for more information. | +| `public StateDefinition getStateDefinition()` | Returns the blockstate definition. Used in a variety of internal places, such as the blockstate parser for commands. | +| `protected final void registerDefaultState(BlockState)` | Registers the default blockstate for this block. Should be called from the block constructor. | +| `public final BlockState defaultBlockState()` | Returns the default blockstate for this block. | +| `public final BlockState withPropertiesOf(BlockState)` | Copies the properties from the given blockstate to this block's default blockstate. This can be a blockstate belonging to a different block, in which case only the properties present on both will be copied. For example, this can be used to copy the rotation and slope properties of a regular rail to a powered rail. | +| `protected ImmutableMap getShapeForEachState(Function)` | Used by the internal shape cache for blockstate-specific shapes. Overridden by big dripleaves to handle the "falling through" when tilting. | +| `public Item asItem()` | Returns the `BlockItem` associated with the block, or `null` if no item is associated. | +| `protected Block asBlock()` | Helper for the abstract `BlockBehaviour` superclass to cast itself to `Block` where needed. | +| `public ItemStack getCloneItemStack(Level, BlockPos, BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Called when the player uses Pick Block (middle mouse button) in creative mode. Typically returns an `ItemStack` containing this block's associated `BlockItem`. Overridden by some blocks, for example flower pots that return the containing plant item here if available. | +| `public String toString()` | Returns the string representation of this block. Format is `"Block{namespace:path}"`, so for example for the block `"minecraft:cobblestone"`, this would be `"Block{minecraft:cobblestone}".` | +| `public String getDescriptionId()` | Returns this block's description ID, a.k.a. translation key. Has the format `"block.."`. For example, for the block `"minecraft:cobblestone"`, this returns `"block.minecraft.cobblestone"`. | +| `public MutableComponent getName()` | Returns a component containing this block's display name, using the translation key. | +| `public float getExplosionResistance()` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns this block's explosion resistance, as set for this block in `BlockBehaviour.Properties`. | +| `public SoundType getSoundType(BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns the sound type set in `BlockBehaviour.Properties`. | +| `public float getFriction()` | Returns the friction value set in `BlockBehaviour.Properties`. | +| `public float getSpeedFactor()` | Returns the speed factor set in `BlockBehaviour.Properties`. | +| `public float getJumpFactor()` | Returns the jump factor set in `BlockBehaviour.Properties`. | +| `public boolean hasDynamicShape()` | Returns whether the block has a dynamic shape or not, as set in `BlockBehaviour.Properties`. | +| `public boolean isRandomlyTicking(BlockState)` | Returns whether the block can be randomly ticked or not, as set in `BlockBehaviour.Properties`. | +| `public void animateTick(BlockState, Level, BlockPos, RandomSource)` | Called periodically on the client side. Does nothing by default, but is overridden by several classes for client side effects, for example torch flame particles. | +| `public void handlePrecipitation(BlockState, Level, BlockPos, Biome.Precipitation)` | Called with a 1 in 16 chance when it is raining to handle weather-dependent behavior. | +| `public BlockState getStateForPlacement(BlockPlaceContext)` | Called when trying to place a `BlockItem` of this block down. The given `BlockPlaceContext` contains information such as the level, the position, the player, the stack and many more that can be used to determine the result. Returns the default block state, but is overridden in a wide range of places. For example, fences use this method to connect to other blocks when placing. | +| `public void setPlacedBy(Level, BlockPos, BlockState, @Nullable LivingEntity, ItemStack)` | Called **after** the blockstate has been placed down by the given `LivingEntity`. Overridden for example by player heads to fetch the associated player skin. | +| `public void playerWillDestroy(Level, BlockPos, BlockState, Player)` | Called immediately **before** the blockstate will be destroyed by the given player. Called regardless of whether the player is using the correct tool. By default, this spawns breaking particles and angers piglins if applicable. Overridden in various places for additional behavior, for example by doors to break their upper/lower part as well. | +| `public void destroy(LevelAcccessor, BlockPos, BlockState)` | Called **after** the blockstate has been destroyed by the player. Used by pistons to destroy the piston head as well if they are activated. | +| `public void playerDestroy(Level, Player, BlockPos, BlockState, @Nullable BlockEntity, ItemStack)` | Called **after** the given player has destroyed the given blockstate with the given tool at the given position in the given level. Called only if the block has used a sufficient tool for drops to spawn, so for example, this will not be called when breaking diamond ore with a wooden pickaxe. Default behaviour handles resource dropping. Overridden for example by beehives that spawn bees in this method when destroyed. | +| `protected void spawnDestroyParticles(Level, Player, BlockPos, BlockState)` | Sends a packet to the client to spawn breaking particles there. Overridden to no-op by fire blocks. | +| `public void popExperience(ServerLevel, BlockPos, int)` | Drops the given amount of experience in the given level at the given position. Respects the `doTileDrops` gamerule. | +| `protected void tryDropExperience(ServerLevel, BlockPos, ItemStack, IntProvider)` | Helper method for dropping experience if the given `ItemStack` is not enchanted with Silk Touch. Currently unused. | +| `public void dropFromExplosion(Explosion)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Whether this block should drop when destroyed by an explosion. `true` by default, overridden to return `false` for TNT. | +| `public void wasExploded(Level, BlockPos, Explosion)` | Called **after** the blockstate has been destroyed by an explosion. | +| `public void stepOn(Level, BlockPos, BlockState, Entity)` | Called when an entity stands on this blockstate. Used for example by magma blocks to apply magma damage. | +| `public void fallOn(Level, BlockState, BlockPos, Entity, float)` | Called when an entity falls onto this blockstate from the given distance. Default behavior is to cause fall damage. Overridden by various blocks that modify fall damage, for example beds or pointed dripstone. | +| `public void updateEntityAfterFallOn(Level, Entity)` | Called **after** an entity falls onto this block and `fallOn` has already been called. This method is mainly responsible for handling the given entity's movement after falling on the block. Default behavior is to cancel any vertical movement. Overridden by beds and slime blocks to perform their bouncing behavior. | +| `public boolean propagatesSkylightDown(BlockState, BlockGetter, BlockPos)` | Whether this block propagates skylight through itself or not. By default, this returns `true` if the block is not a full block and has no fluid state. However, this is overridden by several blocks, such as glass which always let light pass through it. | +| `public boolean isPossibleToRespawnInThis(BlockState)` | Whether respawning in this blockstate is possible or not. Default behaviour is to return `true` if the blockstate is not solid and not a liquid. Overridden by banners, pressure plates and signs to return `true` despite being solid. | +| `public void appendHoverText(ItemStack, @Nullable BlockGetter, List, TooltipFlag)` | Called by the method of the same name in `Item`, this method is responsible for appending hover texts (tooltips) to the item. Does nothing by default. Overridden for example by shulker boxes that add their content tooltips here. | +| `public Holder.Reference builtInRegistryHolder()` | **DEPRECATED.** Internal reference to the builtin block registry holder. **Do not use this, use one of the safer equivalents in `ForgeRegistries.BLOCKS` instead, for example `#getDelegateOrThrow`.** | +| `public Object getRenderPropertiesInternal()` | **DEPRECATED FOR REMOVAL: There is no need for you to use this!** If you are using this somewhere in legacy code, ask in the Discord on how to replace this. NeoForge-added. | +| `public void initializeClient(Consumer consumer)` | Allows for adding custom client-side behavior in the form of a class implementing `IClientBlockExtensions`. NeoForge-added. | +| `public boolean canSustainPlant(BlockState, BlockGetter, BlockPos, Direction, IPlantable)` | Whether this blockstate can sustain the given plant, in the form of an `IPlantable`. Note that this system is flawed and will likely be replaced with a better system in the future. NeoForge-added. | `BlockState` ------------ :::note -Some of these methods are actually located in `BlockBehaviour.BlockStateBase`, the abstract superclass of `BlockState`, or in `IForgeBlockState`, a NeoForge-added interface implemented by `Block` that adds extra utilities for modders to the `BlockState` class. However, for all our intents and purposes, we can treat them as if they were located in `Block` itself. +Some of these methods are actually located in `BlockBehaviour.BlockStateBase`, the abstract superclass of `BlockState`, or in `IForgeBlockState`, a NeoForge-added interface implemented by `Block` that adds extra utilities for modders to the `BlockState` class. However, for all our intents and purposes, we can treat them as if they were located in `BlockState` itself. ::: | Method | Description | @@ -92,4 +162,6 @@ public static final Block OAK_PLANKS = register("oak_planks", new Block(BlockBeh | `offsetType(OffsetType)` | Sets the block's random position offset type. The random position offset slightly offsets a block's hitbox and model position to make it feel more natural. Has three possible values: `NONE` (default), `XZ` (horizontal) and `XYZ` (all directions). Grass and Ferns use `XYZ`, while many flowers and flower-like blocks use `XZ`. | | `requiredFeatures(FeatureFlag...)` | Sets the block's required feature flags. The block will only be actually registered if all the passed feature flags are activated. Currently unused, but historically used for bamboo and cherry wood (among others) when they were in their experimental phase. | +[implementingblockstates]: states.md#implementing-blockstates +[setblock]: states.md#levelsetblock [sounds]: ../gameeffects/sounds.md From f5ca59b2f5199fc55858ae7b3518d57b052a9811 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Wed, 18 Oct 2023 15:46:59 +0200 Subject: [PATCH 05/27] add interactionpipeline.md --- docs/items/interactionpipeline.md | 115 ++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 docs/items/interactionpipeline.md diff --git a/docs/items/interactionpipeline.md b/docs/items/interactionpipeline.md new file mode 100644 index 000000000..7cf3edf6c --- /dev/null +++ b/docs/items/interactionpipeline.md @@ -0,0 +1,115 @@ +The Interaction Pipeline +======================== + +This page aims to make the fairly complex and confusing process of things being right-clicked by the player more understandable, as well as clarifying what result to use where and why. + +What Happens When I Right-Click? +-------------------------------- + +When you right-click anywhere in the world, a number of things happen, depending on what you are currently looking at and what `ItemStack`s are in your hands. A number of methods returning one of two result types (see below) are called. Most of these methods cancel the pipeline if an explicit success or an explicit failure is returned. For the sake of readability, this "explicit success or explicit failure" will be called a "definitive result" from now on. + +- `InputEvent.InteractionKeyMappingTriggered` is fired with the right mouse button and the main hand. If the event is canceled, the pipeline ends. +- Several circumstances are checked, for example that you are not in spectator mode or that all required feature flags for the `ItemStack` in your main hand are enabled. If at least one of these checks fails, the pipeline ends. +- Depending on what you are looking at, different things happen: + - If you are looking at an entity that is within your reach and not outside the world border: + - `PlayerInteractEvent.EntityInteractSpecific` is fired. If the event is canceled, the pipeline ends. + - `Entity#interactAt` will be called **on the entity you are looking at**. If it returns a definitive result, the pipeline ends. + - If you want to add behavior for your own entity, override this method. If you want to add behavior for a vanilla entity, use the event. + - If the entity opens an interface (for example a villager trading GUI or a chest minecart GUI), the pipeline ends. + - `PlayerInteractEvent.EntityInteract` is fired. If the event is canceled, the pipeline ends. + - `Entity#interact` is called **on the entity you are looking at**. If it returns a definitive result, the pipeline ends. + - If you want to add behavior for your own entity, override this method. If you want to add behavior for a vanilla entity, use the event. + - For `Mob`s, the override of `Entity#interact` handles things like leashing and spawning babies when the `ItemStack` in your main hand is a spawn egg, and then defers mob-specific handling to `Mob#mobInteract`. The rules for results for `Entity#interact` apply here as well. + - If the entity you are looking at is a `LivingEntity`, `Item#interactLivingEntity` is called on the `ItemStack` in your main hand. If it returns a definitive result, the pipeline ends. + - If you are looking at a block that is within your reach and not outside the world border: + - `PlayerInteractEvent.RightClickBlock` is fired. If the event is canceled, the pipeline ends. You may also specifically deny only block or item usage in this event. + - `IForgeItem#onItemUseFirst` is called. If it returns a definitive result, the pipeline ends. + - If the player is not sneaking and the event does not deny block usage, `Block#use` is called. If it returns a definitive result, the pipeline ends. + - If the event does not deny item usage, `Item#useOn` is called. If it returns a definitive result, the pipeline ends. +- `Item#use` is called. If it returns a definitive result, the pipeline ends. +- The above process runs a second time, this time with the off hand instead of the main hand. + +Result Types +------------ + +There are two different types of results: `InteractionResult`s and `InteractionResultHolder`s. Depending on the situation, one of the two is used. + +`InteractionResult` is an enum consisting of five values: `SUCCESS`, `CONSUME`, `CONSUME_PARTIAL`, `PASS` and `FAIL`. Additionally, the method `InteractionResult#sidedSuccess` is available, which returns `SUCCESS` on the server and `CONSUME` on the client. + +`InteractionResultHolder` is a wrapper around `InteractionResult` that adds additional context for `T`. `T` can be anything, but in 99.99 percent of cases, it is an `ItemStack`. `InteractionResultHolder` provides wrapper methods for the enum values (`#success`, `#consume`, `#pass` and `#fail`), as well as `#sidedSuccess`, which calls `#success` on the server and `#consume` on the client. + +`Entity#interactAt` +------------------- + +The return type is `InteractionResult`. + +- `InteractionResult#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. +- `InteractionResult.SUCCESS` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. +- `InteractionResult.CONSUME` should be used if the operation should be considered successful, but you do not want the arm to swing. +- `InteractionResult.FAIL` should be used if the item functionality should be considered failed and no further interaction should be performed. **In most cases, this can be replaced with `PASS`!** +- `InteractionResult.PASS` should be used if the operation should be considered neither successful nor failed. The pipeline will continue to evaluate `Entity#interact`. This is the default behavior of this method. + +`Entity#interact` and `Mob#mobInteract` +--------------------------------------- + +The return type is `InteractionResult`. + +- `InteractionResult#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. +- `InteractionResult.SUCCESS` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. +- `InteractionResult.CONSUME` should be used if the operation should be considered successful, but you do not want the arm to swing. +- `InteractionResult.FAIL` should be used if the item functionality should be considered failed and no further interaction should be performed. **In most cases, this can be replaced with `PASS`!** +- `InteractionResult.PASS` should be used if the operation should be considered neither successful nor failed. The pipeline will continue to evaluate `Item#interactLivingEntity`. This is the default behavior of this method. + +`Item#interactLivingEntity` +--------------------------- + +The return type is `InteractionResult`. + +- `InteractionResult#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. +- `InteractionResult.SUCCESS` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. +- `InteractionResult.CONSUME` should be used if the operation should be considered successful, but you do not want the arm to swing. +- `InteractionResult.FAIL` should be used if the item functionality should be considered failed and no further interaction should be performed. **In most cases, this can be replaced with `PASS`!** +- `InteractionResult.PASS` should be used if the operation should be considered neither successful nor failed. The pipeline will continue to evaluate `Item#use`. This is the default behavior of this method. + +`IForgeItem#onItemUseFirst` +--------------------------- + +The return type is `InteractionResult`. + +- `InteractionResult.SUCCESS` should be used if the item functionality should be considered successful and no further interaction should be performed. +- `InteractionResult.FAIL` should be used if the item functionality should be considered failed and no further interaction should be performed. +- `InteractionResult.PASS` should be used if the item functionality should be considered neither successful nor failed. The pipeline will continue to evaluate `Block#use`. This is the default behavior of this method. + +`Block#use` +----------- + +The return type is `InteractionResult`. + +- `InteractionResult#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. +- `InteractionResult.SUCCESS` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. +- `InteractionResult.CONSUME` should be used if the operation should be considered successful, but you do not want the arm to swing. +- `InteractionResult.FAIL` should be used if the item functionality should be considered failed and no further interaction should be performed. **In most cases, this can be replaced with `PASS`!** +- `InteractionResult.PASS` should be used if the operation should be considered neither successful nor failed. The pipeline will continue to evaluate `Item#useOn`. This is the default behavior of this method. + +`Item#useOn` +------------ + +The return type is `InteractionResult`. + +- `InteractionResult#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. +- `InteractionResult.SUCCESS` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. +- `InteractionResult.CONSUME` should be used if the operation should be considered successful, but you do not want the arm to swing. +- `InteractionResult.CONSUME_PARTIAL` should be used if the operation should be considered successful, but you do not want the arm to swing or an `ITEM_USED` stat point to be awarded. +- `InteractionResult.FAIL` should be used if the operation should be considered failed and no further interaction should be performed. +- `InteractionResult.PASS` should be used if the operation should be considered neither successful nor failed. The pipeline will continue to evaluate `Item#use`. This is the default behavior of this method. + +`Item#use` +---------- + +The return type is `InteractionResultHolder`. The resulting `ItemStack` in the `InteractionResultHolder` replaces the `ItemStack` the usage was initiated with, if it has changed. The default implementation of `Item#use` returns `InteractionResultHolder#consume` when the item is edible and the player can eat the item (because they are hungry, or because the item is always edible), `InteractionResultHolder#fail` when the item is edible but the player cannot eat the item, and `InteractionResultHolder#pass` if the item is not edible. + +- `InteractionResultHolder#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. +- `InteractionResultHolder#success` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. +- `InteractionResultHolder#consume` should be used if the operation should be considered successful, but you do not want the arm to swing. +- `InteractionResultHolder#fail` should be used if the operation should be considered failed and no further interaction should be performed. +- `InteractionResultHolder#pass` should be used if the operation should be considered neither successful nor failed. This will end the pipeline for this hand, but may run the pipeline for the other hand if applicable. From 2dcc08c7bc9677e39984425be3e20814e353f311 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Wed, 18 Oct 2023 20:42:47 +0200 Subject: [PATCH 06/27] add documentation for methods of BlockBehaviour --- docs/blocks/reference.md | 137 +++++++++++++++++++++++++++------------ 1 file changed, 94 insertions(+), 43 deletions(-) diff --git a/docs/blocks/reference.md b/docs/blocks/reference.md index dc4fcae7f..923f4a2a2 100644 --- a/docs/blocks/reference.md +++ b/docs/blocks/reference.md @@ -43,49 +43,97 @@ Some of these methods are actually located in `BlockBehaviour`, the abstract sup For methods with a `BlockState` parameter, it can be generally assumed that the given blockstate is a state of this block (unless stated otherwise). ::: -| Method | Description | -|---------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `protected void createBlockStateDefinition(StateDefinition.Builder)` | Defines the block state properties this block has. See [Implementing Blockstates][implementingblockstates] for more information. | -| `public StateDefinition getStateDefinition()` | Returns the blockstate definition. Used in a variety of internal places, such as the blockstate parser for commands. | -| `protected final void registerDefaultState(BlockState)` | Registers the default blockstate for this block. Should be called from the block constructor. | -| `public final BlockState defaultBlockState()` | Returns the default blockstate for this block. | -| `public final BlockState withPropertiesOf(BlockState)` | Copies the properties from the given blockstate to this block's default blockstate. This can be a blockstate belonging to a different block, in which case only the properties present on both will be copied. For example, this can be used to copy the rotation and slope properties of a regular rail to a powered rail. | -| `protected ImmutableMap getShapeForEachState(Function)` | Used by the internal shape cache for blockstate-specific shapes. Overridden by big dripleaves to handle the "falling through" when tilting. | -| `public Item asItem()` | Returns the `BlockItem` associated with the block, or `null` if no item is associated. | -| `protected Block asBlock()` | Helper for the abstract `BlockBehaviour` superclass to cast itself to `Block` where needed. | -| `public ItemStack getCloneItemStack(Level, BlockPos, BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Called when the player uses Pick Block (middle mouse button) in creative mode. Typically returns an `ItemStack` containing this block's associated `BlockItem`. Overridden by some blocks, for example flower pots that return the containing plant item here if available. | -| `public String toString()` | Returns the string representation of this block. Format is `"Block{namespace:path}"`, so for example for the block `"minecraft:cobblestone"`, this would be `"Block{minecraft:cobblestone}".` | -| `public String getDescriptionId()` | Returns this block's description ID, a.k.a. translation key. Has the format `"block.."`. For example, for the block `"minecraft:cobblestone"`, this returns `"block.minecraft.cobblestone"`. | -| `public MutableComponent getName()` | Returns a component containing this block's display name, using the translation key. | -| `public float getExplosionResistance()` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns this block's explosion resistance, as set for this block in `BlockBehaviour.Properties`. | -| `public SoundType getSoundType(BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns the sound type set in `BlockBehaviour.Properties`. | -| `public float getFriction()` | Returns the friction value set in `BlockBehaviour.Properties`. | -| `public float getSpeedFactor()` | Returns the speed factor set in `BlockBehaviour.Properties`. | -| `public float getJumpFactor()` | Returns the jump factor set in `BlockBehaviour.Properties`. | -| `public boolean hasDynamicShape()` | Returns whether the block has a dynamic shape or not, as set in `BlockBehaviour.Properties`. | -| `public boolean isRandomlyTicking(BlockState)` | Returns whether the block can be randomly ticked or not, as set in `BlockBehaviour.Properties`. | -| `public void animateTick(BlockState, Level, BlockPos, RandomSource)` | Called periodically on the client side. Does nothing by default, but is overridden by several classes for client side effects, for example torch flame particles. | -| `public void handlePrecipitation(BlockState, Level, BlockPos, Biome.Precipitation)` | Called with a 1 in 16 chance when it is raining to handle weather-dependent behavior. | -| `public BlockState getStateForPlacement(BlockPlaceContext)` | Called when trying to place a `BlockItem` of this block down. The given `BlockPlaceContext` contains information such as the level, the position, the player, the stack and many more that can be used to determine the result. Returns the default block state, but is overridden in a wide range of places. For example, fences use this method to connect to other blocks when placing. | -| `public void setPlacedBy(Level, BlockPos, BlockState, @Nullable LivingEntity, ItemStack)` | Called **after** the blockstate has been placed down by the given `LivingEntity`. Overridden for example by player heads to fetch the associated player skin. | -| `public void playerWillDestroy(Level, BlockPos, BlockState, Player)` | Called immediately **before** the blockstate will be destroyed by the given player. Called regardless of whether the player is using the correct tool. By default, this spawns breaking particles and angers piglins if applicable. Overridden in various places for additional behavior, for example by doors to break their upper/lower part as well. | -| `public void destroy(LevelAcccessor, BlockPos, BlockState)` | Called **after** the blockstate has been destroyed by the player. Used by pistons to destroy the piston head as well if they are activated. | -| `public void playerDestroy(Level, Player, BlockPos, BlockState, @Nullable BlockEntity, ItemStack)` | Called **after** the given player has destroyed the given blockstate with the given tool at the given position in the given level. Called only if the block has used a sufficient tool for drops to spawn, so for example, this will not be called when breaking diamond ore with a wooden pickaxe. Default behaviour handles resource dropping. Overridden for example by beehives that spawn bees in this method when destroyed. | -| `protected void spawnDestroyParticles(Level, Player, BlockPos, BlockState)` | Sends a packet to the client to spawn breaking particles there. Overridden to no-op by fire blocks. | -| `public void popExperience(ServerLevel, BlockPos, int)` | Drops the given amount of experience in the given level at the given position. Respects the `doTileDrops` gamerule. | -| `protected void tryDropExperience(ServerLevel, BlockPos, ItemStack, IntProvider)` | Helper method for dropping experience if the given `ItemStack` is not enchanted with Silk Touch. Currently unused. | -| `public void dropFromExplosion(Explosion)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Whether this block should drop when destroyed by an explosion. `true` by default, overridden to return `false` for TNT. | -| `public void wasExploded(Level, BlockPos, Explosion)` | Called **after** the blockstate has been destroyed by an explosion. | -| `public void stepOn(Level, BlockPos, BlockState, Entity)` | Called when an entity stands on this blockstate. Used for example by magma blocks to apply magma damage. | -| `public void fallOn(Level, BlockState, BlockPos, Entity, float)` | Called when an entity falls onto this blockstate from the given distance. Default behavior is to cause fall damage. Overridden by various blocks that modify fall damage, for example beds or pointed dripstone. | -| `public void updateEntityAfterFallOn(Level, Entity)` | Called **after** an entity falls onto this block and `fallOn` has already been called. This method is mainly responsible for handling the given entity's movement after falling on the block. Default behavior is to cancel any vertical movement. Overridden by beds and slime blocks to perform their bouncing behavior. | -| `public boolean propagatesSkylightDown(BlockState, BlockGetter, BlockPos)` | Whether this block propagates skylight through itself or not. By default, this returns `true` if the block is not a full block and has no fluid state. However, this is overridden by several blocks, such as glass which always let light pass through it. | -| `public boolean isPossibleToRespawnInThis(BlockState)` | Whether respawning in this blockstate is possible or not. Default behaviour is to return `true` if the blockstate is not solid and not a liquid. Overridden by banners, pressure plates and signs to return `true` despite being solid. | -| `public void appendHoverText(ItemStack, @Nullable BlockGetter, List, TooltipFlag)` | Called by the method of the same name in `Item`, this method is responsible for appending hover texts (tooltips) to the item. Does nothing by default. Overridden for example by shulker boxes that add their content tooltips here. | -| `public Holder.Reference builtInRegistryHolder()` | **DEPRECATED.** Internal reference to the builtin block registry holder. **Do not use this, use one of the safer equivalents in `ForgeRegistries.BLOCKS` instead, for example `#getDelegateOrThrow`.** | -| `public Object getRenderPropertiesInternal()` | **DEPRECATED FOR REMOVAL: There is no need for you to use this!** If you are using this somewhere in legacy code, ask in the Discord on how to replace this. NeoForge-added. | -| `public void initializeClient(Consumer consumer)` | Allows for adding custom client-side behavior in the form of a class implementing `IClientBlockExtensions`. NeoForge-added. | -| `public boolean canSustainPlant(BlockState, BlockGetter, BlockPos, Direction, IPlantable)` | Whether this blockstate can sustain the given plant, in the form of an `IPlantable`. Note that this system is flawed and will likely be replaced with a better system in the future. NeoForge-added. | +| Method | Description | +|---------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `protected void createBlockStateDefinition(StateDefinition.Builder)` | Defines the block state properties this block has. See [Implementing Blockstates][implementingblockstates] for more information. | +| `public StateDefinition getStateDefinition()` | Returns the blockstate definition. Used in a variety of internal places, such as the blockstate parser for commands. | +| `protected final void registerDefaultState(BlockState)` | Registers the default blockstate for this block. Should be called from the block constructor. | +| `public final BlockState defaultBlockState()` | Returns the default blockstate for this block. | +| `public final BlockState withPropertiesOf(BlockState)` | Copies the properties from the given blockstate to this block's default blockstate. This can be a blockstate belonging to a different block, in which case only the properties present on both will be copied. For example, this can be used to copy the rotation and slope properties of a regular rail to a powered rail. | +| `public FluidState getFluidState(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getFluidState` instead.** Returns the fluid state of this block. Returns `Fluids.EMPTY.defaultFluidState()` by default. Waterloggable blocks override this to return `Fluids.WATER.defaultFluidState()` if their `waterlogged` property is set to `true`. | +| `public Item asItem()` | Returns the `BlockItem` associated with the block, or `null` if no item is associated. | +| `protected Block asBlock()` | Helper for the abstract `BlockBehaviour` superclass to cast itself to `Block` where needed. | +| `public ItemStack getCloneItemStack(Level, BlockPos, BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Called when the player uses Pick Block (middle mouse button) in creative mode. Typically returns an `ItemStack` containing this block's associated `BlockItem`. Overridden by some blocks; for example, flower pots return the containing plant item here if available. | +| `public String toString()` | Returns the string representation of this block. Format is `"Block{namespace:path}"`, so for example for the block `"minecraft:cobblestone"`, this would be `"Block{minecraft:cobblestone}".` | +| `public String getDescriptionId()` | Returns this block's description ID, a.k.a. translation key. Has the format `"block.."`. For example, for the block `"minecraft:cobblestone"`, this returns `"block.minecraft.cobblestone"`. | +| `public MutableComponent getName()` | Returns a component containing this block's display name, using the translation key. | +| `protected boolean isAir(BlockState)` | Returns whether the given blockstate is air or not, set in `BlockBehaviour.Properties`. | +| `public MapColor defaultMapColor()` | Returns the `MapColor` of the default block state. | +| `public float defaultDestroyTime()` | Returns the destroy speed of the default block state. | +| `public float getExplosionResistance()` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns this block's explosion resistance, as set for this block in `BlockBehaviour.Properties`. | +| `public SoundType getSoundType(BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns the sound type set in `BlockBehaviour.Properties`. | +| `public float getFriction()` | Returns the friction value set in `BlockBehaviour.Properties`. | +| `public float getSpeedFactor()` | Returns the speed factor set in `BlockBehaviour.Properties`. | +| `public float getJumpFactor()` | Returns the jump factor set in `BlockBehaviour.Properties`. | +| `public float getMaxHorizontalOffset()` | Returns the max horizontal offset for blocks with random offset. Default value is 0.25, Pointed Dripstone overrides this to 0.125. See `BlockBehaviour.Properties#offsetType` for more information. | +| `public float getMaxVerticalOffset()` | Returns the max vertical offset for blocks with random offset. Default value is 0.2, Small Dripleaf overrides this to 0.1. See `BlockBehaviour.Properties#offsetType` for more information. | +| `public FeatureFlagSet requiredFeatures()` | Returns the required features set in `BlockBehaviour.Properties`. | +| `public boolean hasDynamicShape()` | Returns whether the block has a dynamic shape or not, as set in `BlockBehaviour.Properties`. | +| `public boolean isRandomlyTicking(BlockState)` | Returns whether the block can be randomly ticked or not, as set in `BlockBehaviour.Properties`. | +| `public final ResourceLocation getLootTable()` | Returns the loot table of the block, set in `BlockBehaviour.Properties`. | +| `public void tick(BlockState, ServerLevel, BlockPos, RandomSource)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#tick` instead.** Performs a tick (update) on the blockstate. This is called every tick (1 / 20 seconds). Does nothing by default. For example, chests and chest-like blocks check if the player is still in range for them to stay opened here, and redstone updates are performed here as well. | +| `public void randomTick(BlockState, ServerLevel, BlockPos, RandomSource)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#randomTick` instead.** Performs a random tick on the blockstate. For example, plants grow here, snow and ice melt here, and copper oxidizes here. The default implementation calls `Block#tick(BlockState, ServerLevel, BlockPos, RandomSource)`. | +| `public void animateTick(BlockState, Level, BlockPos, RandomSource)` | Called every tick (1 / 20 seconds) on the client side. Does nothing by default, but is overridden by several classes for client side effects, for example torch flame particles. | +| `public void handlePrecipitation(BlockState, Level, BlockPos, Biome.Precipitation)` | Called every tick (1 / 20 seconds) with a 1 in 16 chance when it is raining to handle weather-dependent behavior. | +| `public BlockState canBeReplaced(BlockState, BlockPlaceContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canBeReplaced` instead.** Returns whether the state can be replaced by another block. Returns `false` if the `replaceable` field in `BlockBehaviour.Properties` is `false` or if the blockstate being placed is the same as the given blockstate (since you obviously cannot replace grass with grass), and `true` if neither of those apply. Overridden by some blocks, mainly decorative blocks, for various additions to that rule. | +| `public BlockState canBeReplaced(BlockState, Fluid)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canBeReplaced` instead.** Variant of `#canBeReplaced(BlockState, BlockPlaceContext)` that is called when a block would be replaced by a fluid. Returns `false` if the `replaceable` field in `BlockBehaviour.Properties` is `false` or if the given blockstate is not solid, and `true` otherwise. Overridden by end portals and end gateways to always return `false`. | +| `public BlockState getStateForPlacement(BlockPlaceContext)` | Called when trying to place a `BlockItem` of this block down. The given `BlockPlaceContext` contains information such as the level, the position, the player, the stack and many more that can be used to determine the result. Returns the default block state, but is overridden in a wide range of places. For example, fences use this method to connect to other blocks when placing. | +| `public void onPlace(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onPlace` instead.** Called when the blockstate is placed. Parameter order is `state, level, position, oldStateAtThatPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Overridden in several places, mostly for performing post-placement behavior. | +| `public void setPlacedBy(Level, BlockPos, BlockState, @Nullable LivingEntity, ItemStack)` | Called **after** the blockstate has been placed down by the given `LivingEntity`. Overridden for example by player heads to fetch the associated player skin. | +| `public boolean canSurvive(BlockState, LevelReader, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canSurvive` instead.** Returns whether the blockstate can survive here or not. Returns `true` by default. Overridden by various blocks that have placement requirements, for example plants that need to check if they are placed on the correct soil, or hanging lanterns that check if they are actually still hanging. | +| `public BlockState rotate(BlockState, Rotation)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#rotate` instead.** Returns the state to use after rotating the block with the given rotation. Returns the given state by default. Overridden by all blocks with a `facing` property to consider said `facing` property. | +| `public BlockState mirror(BlockState, Mirror)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#mirror` instead.** Returns the state to use after mirroring the block with the given mirror. Returns the given state by default. Overridden by all blocks with a `facing` property to consider said `facing` property. | +| `public InteractionResult use(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#use` instead.** Called as part of the [Interaction Pipeline][interactionpipeline] when a block is activated or used. For example, this is where pressing a button or opening a crafting table GUI happens. For details on when exactly this is called and what to use as the return value, please refer to the [explanation of `Block#use` in the Interaction Pipeline article][blockuse]. | +| `public boolean triggerEvent(BlockState, Level, BlockPos, int, int)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#triggerEvent` instead.** Called on the server when `Level#blockEvent` is called. Called on the client as well if it returned `true` on the server. The primary use of this mechanic is to notify the other side of changes that cannot be sent via a block entity. The type of event is identified by the id parameter (first `int` parameter). Additional info can be passed into the second `int` parameter. For example, pistons use the second `int` parameter to specify the direction, and shulker boxes use the second parameter for specifying how many players are currently accessing the shulker box. | +| `public MenuProvider getMenuProvider(BlockState, Level, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getMenuProvider` instead.** Returns a menu provider to show when right-clicking the block. Returns `null` by default. Overridden by blocks that don't have a `BlockEntity` but still have a GUI, such as the Crafting Table, the Smithing Table or the Grindstone. | +| `public void attack(BlockState, ServerLevel, BlockPos, Player)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#attack` instead.** Called when a player begins breaking the block. For example, note blocks play their note here, and the dragon egg teleports away. The default implementation is empty. | +| `public void onProjectileHit(Level, BlockState, BlockHitResult, Projectile)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onProjectileHit` instead.** Called when a `Projectile` (for example an arrow or a fireball) hits the blockstate. Does nothing by default. For example, TNT ignites itself here when hit with a burning projectile. | +| `public void playerWillDestroy(Level, BlockPos, BlockState, Player)` | Called immediately **before** the blockstate will be destroyed by the given player. Called regardless of whether the player is using the correct tool. By default, this spawns breaking particles and angers piglins if applicable. Overridden in various places for additional behavior, for example by doors to break their upper/lower part as well. | +| `public void onRemove(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onRemove` instead.** Called when the blockstate is removed. Parameter order is `state, level, position, newStateAtThatPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Default behavior removes a block entity present at the position from the level, if applicable. Overridden in several places, mostly to either spill out container content or to perform a final redstone update. | +| `public void destroy(LevelAcccessor, BlockPos, BlockState)` | Called **after** the blockstate has been destroyed by the player. Used by pistons to destroy the piston head as well if they are activated. | +| `public void playerDestroy(Level, Player, BlockPos, BlockState, @Nullable BlockEntity, ItemStack)` | Called **after** the given player has destroyed the given blockstate with the given tool at the given position in the given level. Called only if the block has used a sufficient tool for drops to spawn, so for example, this will not be called when breaking diamond ore with a wooden pickaxe. Default behaviour handles resource dropping. Overridden for example by beehives that spawn bees in this method when destroyed. | +| `protected void spawnDestroyParticles(Level, Player, BlockPos, BlockState)` | Sends a packet to the client to spawn breaking particles there. Overridden to no-op by fire blocks. | +| `public List getDrops(BlockState, LootParams.Builder)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getDrops` instead.** Rolls the loot table for the block with blockstate context. Overridden by some blocks that add custom modifications to the results, such as shulker boxes that add their inventory to the dropped `ItemStack`. | +| `public void popExperience(ServerLevel, BlockPos, int)` | Drops the given amount of experience in the given level at the given position. Respects the `doTileDrops` gamerule. | +| `protected void tryDropExperience(ServerLevel, BlockPos, ItemStack, IntProvider)` | Helper method for dropping experience if the given `ItemStack` is not enchanted with Silk Touch. Currently unused. | +| `public void spawnAfterBreak(BlockState, ServerLevel, BlockPos, ItemStack, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#spawnAfterBreak` instead.** Spawns entities after breaking this blockstate. The `boolean` parameter determines whether to drop experience or not. The default implementation drops experience if the `boolean` parameter is `true` and `Block#getExpDrop` returns more than 0. Overridden by ore blocks and spawners to drop xp, and by infested blocks to spawn silverfish. | +| `public void dropFromExplosion(Explosion)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Whether this block should drop when destroyed by an explosion. `true` by default, overridden to return `false` for TNT. | +| `public void wasExploded(Level, BlockPos, Explosion)` | Called **after** the blockstate has been destroyed by an explosion. | +| `public void stepOn(Level, BlockPos, BlockState, Entity)` | Called when an entity stands on this blockstate. Used for example by magma blocks to apply magma damage. | +| `public void entityInside(BlockState, ServerLevel, BlockPos, Entity)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#entityInside` instead.** Called when the given entity is inside this blockstate. Does nothing by default. For example, fire blocks ignite entities that stand in them here. | +| `public void fallOn(Level, BlockState, BlockPos, Entity, float)` | Called when an entity falls onto this blockstate from the given distance. Default behavior is to cause fall damage. Overridden by various blocks that modify fall damage, for example beds or pointed dripstone. | +| `public void updateEntityAfterFallOn(Level, Entity)` | Called **after** an entity falls onto this block and `#fallOn` has already been called. This method is mainly responsible for handling the given entity's movement after falling on the block. Default behavior is to cancel any vertical movement. Overridden by beds and slime blocks to perform their bouncing behavior. | +| `public boolean propagatesSkylightDown(BlockState, BlockGetter, BlockPos)` | Whether this block propagates skylight through itself or not. By default, this returns `true` if the block is not a full block and has no fluid state. However, this is overridden by several blocks, such as glass which always lets light pass through it. | +| `public boolean skipRendering(BlockState, BlockState, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#skipRendering` instead.** Whether this block's rendering should be skipped or not, given the context of the adjacent blockstate (second `BlockState` parameter). Used for example by glass to not render itself over and over in a glass layer that's several blocks wide. | +| `public RenderShape getRenderShape(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getRenderShape` instead.** Defines how the block should be rendered. Possible values are `RenderShape.ENTITYBLOCK_ANIMATED` for blocks that use a [`BlockEntityRenderer`][ber], `RenderShape.MODEL` if a JSON model or a mix of JSON model and `BlockEntityRenderer` is used, and `RenderShape.INVISIBLE` to not render at all. The default value is `RenderShape.MODEL`. | +| `public VoxelShape getShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getShape` instead.** Returns the block's selection shape. Returns a 1x1x1 block shape by default. Overridden by blocks that have a non-1x1x1 shape, for example slabs, stairs, walls, fences, carpets, beds and many many others. | +| `public VoxelShape getBlockSupportShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getBlockSupportShape` instead.** Returns the shape to use when checking if this block can support another block. Returns the collision shape by default. Overridden by some blocks with unusual collision shapes, for example soul sand or mud, to still support blocks on top of them. | +| `public VoxelShape getInteractionShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getInteractionShape` instead.** Returns the shape to use for special interactions with this block. Returns an empty shape by default. Overridden by blocks that have different interactions depending on the side used, for example hoppers or cauldrons. | +| `public VoxelShape getVisualShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getVisualShape` instead.** Returns what is considered the block's visual shape. Returns the collision shape by default. Overridden by some blocks that consider the visual shape to be the selection shape, such as fences and iron bars. | +| `public VoxelShape getCollisionShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getCollisionShape` instead.** Returns the block's collision shape, a.k.a. hitbox. Returns the selection shape if collision is enabled (as set in the `BlockBehaviour.Properties`) and an empty shape if not. Overridden by blocks where the selection shape is different from the collision shape, such as walls, fence gates, lecterns or soul sand. | +| `public VoxelShape getOcclusionShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getOcclusionShape` instead.** Returns the shape to use for occlusion by the light engine. Returns the normal shape by default. Overridden by some blocks, for example fences or lecterns, to return a smaller shape. | +| `public boolean isCollisionShapeFullBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isCollisionShapeFullBlock` instead.** Returns `true` if the block's collision shape is a full block, `false` if not. | +| `public boolean isOcclusionShapeFullBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isOcclusionShapeFullBlock` instead.** Returns `true` if the block's occlusion shape is a full block, `false` if not. | +| `public boolean useShapeForLightOcclusion(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#useShapeForLightOcclusion` instead.** Whether the block should use its shape for light occlusion or not. Returns `false` by default, but is overridden to `true` by many blocks that don't have a full block shape, such as slabs, stairs or sculk sensors. | +| `public int getLightBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getLightBlock` instead.** Returns how much the block blocks light. Returns 15 for solid blocks, 0 if `Block#propagatesSkylightDown(Level, BlockPos)` returns `true`, and 1 otherwise. Overridden to be 15 by Tinted Glass, despite being a non-solid block. | +| `public float getShadeBrightness(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getShadeBrightness` instead.** Returns the shade brightness of this block, used by the light engine. Returns 0.2 for solid blocks and 1.0 for all other blocks by default. Overridden by some blocks with unusual collision shapes, for example soul sand or mud, to still act like a solid block in this situation. | +| `public boolean updateShape(BlockState, Direction, BlockState, LevelAccessor, BlockPos, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#updateShape` instead.** Updates the blockstate given the neighbor context. Parameter order is `ownState, neighborDirection, neighborState, level, ownPosition, neighborPosition`. Returns itself by default, overridden in a lot of places, for example by fences, walls or blocks that are attached to another block. | +| `public void updateIndirectNeighbourShapes(BlockState, BlockGetter, BlockPos, int, int)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#updateIndirectNeighbourShapes` instead.** Updates the diagonal neighbor blockstates. The `int` parameters are the flags and worldgen recursion values, see `Block.updateOrDestroy` for a more detailed explanation of those. Does nothing by default, but is overridden by redstone wires. | +| `public boolean neighborChanged(BlockState, Level, BlockPos, Block, BlockPos, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#neighborChanged` instead.** Called when a neighboring block has been changed. Parameter order is `state, level, fromPosition, movedBlock, toPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Overridden in several places, mostly with some relation to redstone. | +| `protected ImmutableMap getShapeForEachState(Function)` | Used by the internal shape cache for blockstate-specific shapes. Overridden by big dripleaves to handle the "falling through" when tilting. | +| `public long getSeed(BlockState, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getSeed` instead.** Returns a seed to use when randomly selecting one of multiple possible models. | +| `public boolean hasAnalogOutputSignal(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#hasAnalogOutputSignal` instead.** Whether this block has a redstone output signal that comparators can listen to. This is not saying that the block always emits a redstone signal. To get the actually emitted redstone signal, use `Block#getAnalogOutputSignal`. | +| `public int getAnalogOutputSignal(BlockState, Level, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getAnalogOutputSignal` instead.** Returns the analog redstone value emitted by this block, which can be read by comparators. Returns 0 by default. Overridden by various containers and redstone components to return their redstone signal value, for example a value from 0 to 15 by hoppers. This does not return the redstone power value of the block itself, see `Block#getSignal` for that. | +| `public int getSignal(BlockState, ServerLevel, BlockPos, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getSignal` instead.** Returns the **outgoing** redstone signal strength of the block in the given direction. Returns 0 by default. For example, this would return 15 for an activated lever and 0 for a deactivated lever. | +| `public int getDirectSignal(BlockState, ServerLevel, BlockPos, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getDirectSignal` instead.** Returns the **incoming** redstone signal strength of the block from the given direction. Returns 0 by default. Overridden by blocks that only accept redstone power if it comes from the correct side, such as redstone torches. | +| `public boolean isSignalSource(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isSignalSource` instead.** Whether the block is a signal source. Note that vanilla doesn't actually use this a lot, only checking it in redstone wires and rails and overriding it to unconditionally return `true` in a lot of places where it does not actually make sense. This is because most of the time, vanilla simply checks the `powered` blockstate property instead. | +| `public boolean isPathfindable(BlockState, BlockGetter, BlockPos, PathComputationType)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isPathfindable` instead.** Whether mobs can pathfind over the blockstate or not. Default behavior checks for a full block, or for water if the PathComputationType is `WATER`. Overridden to `false` in a variety of places, for example soul sand, respawn anchors or various non-full blocks, just to be sure. | +| `public boolean isPossibleToRespawnInThis(BlockState)` | Whether respawning in this blockstate is possible or not. Default behaviour is to return `true` if the blockstate is not solid and not a liquid. Overridden by banners, pressure plates and signs to return `true` despite being solid. | +| `public void appendHoverText(ItemStack, @Nullable BlockGetter, List, TooltipFlag)` | Called by the method of the same name in `Item`, this method is responsible for appending hover texts (tooltips) to the item. Does nothing by default. Overridden for example by shulker boxes that add their content tooltips here. | +| `public Holder.Reference builtInRegistryHolder()` | **DEPRECATED.** Internal reference to the builtin block registry holder. **Do not use this, use one of the safer equivalents in `ForgeRegistries.BLOCKS` instead, for example `#getDelegateOrThrow`.** | +| `public Object getRenderPropertiesInternal()` | **DEPRECATED FOR REMOVAL: There is no need for you to use this!** If you are using this somewhere in legacy code, ask in the Discord on how to replace this. NeoForge-added. | +| `public void initializeClient(Consumer consumer)` | Allows for adding custom client-side behavior in the form of a class implementing `IClientBlockExtensions`. NeoForge-added. | +| `public boolean canSustainPlant(BlockState, BlockGetter, BlockPos, Direction, IPlantable)` | Whether this blockstate can sustain the given plant, in the form of an `IPlantable`. Note that this system is flawed and will likely be replaced with a better system in the future. NeoForge-added. | `BlockState` ------------ @@ -162,6 +210,9 @@ public static final Block OAK_PLANKS = register("oak_planks", new Block(BlockBeh | `offsetType(OffsetType)` | Sets the block's random position offset type. The random position offset slightly offsets a block's hitbox and model position to make it feel more natural. Has three possible values: `NONE` (default), `XZ` (horizontal) and `XYZ` (all directions). Grass and Ferns use `XYZ`, while many flowers and flower-like blocks use `XZ`. | | `requiredFeatures(FeatureFlag...)` | Sets the block's required feature flags. The block will only be actually registered if all the passed feature flags are activated. Currently unused, but historically used for bamboo and cherry wood (among others) when they were in their experimental phase. | +[ber]: ../blockentities/ber.md +[blockuse]: ../items/interactionpipeline.md#blockuse [implementingblockstates]: states.md#implementing-blockstates +[interactionpipeline]: ../items/interactionpipeline.md [setblock]: states.md#levelsetblock [sounds]: ../gameeffects/sounds.md From a5d4da1fe086bcb11ae8faabf1d55550b8d95c33 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Thu, 19 Oct 2023 01:01:07 +0200 Subject: [PATCH 07/27] add common block pipelines --- docs/blocks/index.md | 96 ++++++++++++++++++-- docs/blocks/reference.md | 184 ++++++++++++++++++++------------------- docs/blocks/states.md | 6 +- 3 files changed, 187 insertions(+), 99 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 5e4a1503f..97d2a6959 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -47,7 +47,7 @@ public static final RegistryObject MY_BETTER_BLOCK = BLOCKS.register("my_ .lightLevel(state -> 7))); ``` -For further documentation, see the [`BlockBehaviour.Properties` reference][reference_properties]. For more examples, or to look at the values used by Minecraft, have a look at the `Blocks` class. +For further documentation, see the [`BlockBehaviour.Properties` reference][propertiesreference]. For more examples, or to look at the values used by Minecraft, have a look at the `Blocks` class. :::note It is important to understand that a block in the world is not the same thing as in an inventory. What looks like a block in an inventory is actually a `BlockItem`, a special type of [item] that places a block when used. This also means that things like the creative tab or the max stack size are handled by the corresponding `BlockItem`. @@ -57,7 +57,7 @@ A `BlockItem` must be registered separately from the block. This is because a bl ### More Functionality -Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a non-1x1x1 hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; these are documented in the [`Block` reference][reference_block]. +Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a non-1x1x1 hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; these are documented in the [`Block` reference][blockreference]. See also the Using blocks section below for some of the most common use cases for blocks. If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity][blockentities] should be used. The rule of thumb here is that if you have a finite amount of states, use blockstates, and if you have an infinite or near-infinite amount of states, use a block entity. @@ -70,15 +70,99 @@ To apply a simple texture to a block, you must add a blockstate JSON, a model JS Using Blocks ------------ -Blocks are very rarely directly used to do things. The main purpose of a block class is to define behavior of a block. The game then runs that behavior through `BlockState`s, often passing them into the `Block`'s functionality methods as a parameter. +Blocks are very rarely directly used to do things. In fact, probably two of the most common operations in all of Minecraft - getting the block at a position, and setting a block at a position - use blockstates, not blocks. The general design approach is to have the block define behavior, but have the behavior actually run through blockstates. Due to this, `BlockState`s are often passed to methods of `Block` as a parameter. For more information on how blockstates are used, and on how to get one from a block, see [Using Blockstates][usingblockstates]. -For more information on how blockstates are used, see [Using Blockstates][usingblockstates]. +In several situations, multiple methods of `Block` are used at different times. The following subsections list the most common block-related pipelines. Unless specified otherwise, all methods are called on both logical sides. + +### Placing a Block + +Block placement logic is called from `BlockItem#useOn` (or some subclass's implementation thereof, such as in `PlaceOnWaterBlockItem`, which is used for lily pads). For more information on how the game gets there, see the [Interaction Pipeline][interactionpipeline]. + +- Several prerequisites are checked, for example that you are not in spectator mode, that all required feature flags for the block are enabled or that the block in question is not outside the world border. If at least one of these checks fails, the pipeline ends. +- `Block#canBeReplaced` is called for the block currently at the position where the block is tried to place. If it returns `false`, the pipeline ends. +- `Block#getStateForPlacement` is called. +- `Block#canSurvive` is called with the blockstate obtained in the previous step. If it returns `false`, the pipeline ends. +- The blockstate is set into the level via a `Level#setBlock` call. + - In that `Level#setBlock` call, `Block#onPlace` is called. +- `Block#setPlacedBy` is called. + +### Breaking a Block + +Breaking a block is a bit more complex, as it requires time. The process can be roughly divided into four stages: "initiating", "mining", "actually breaking" and "finishing". + +- When the left mouse button is clicked, the "initiating" stage is entered. +- Now, the left mouse button needs to be held down, entering the "mining" stage. **This stage's methods are called every tick.** +- If the "continuing" stage is not interrupted (by releasing the left mouse button) and the block is broken, the "actually breaking" stage is entered. +- Under all circumstances, no matter if the block was actually broken or not, the "finishing" stage is entered. + +Or for those who prefer pseudocode: + +```java +leftClick(); +initiatingStage(); +while (leftClickIsBeingHeld()) { + miningStage(); + if (blockIsBroken()) { + actuallyBreakingStage(); + break; + } +} +finishingStage(); +``` + +The following subsections further break down these stages into actual method calls. + +#### The "Initiating" Stage + +- `InputEvent.InteractionKeyMappingTriggered` is fired with the left mouse button and the main hand. If the event is canceled, the pipeline ends. +- Several prerequisites are checked, for example that you are not in spectator mode, that all required feature flags for the `ItemStack` in your main hand are enabled or that the block in question is not outside the world border. If at least one of these checks fails, the pipeline ends. +- `PlayerInteractEvent.LeftClickBlock` is fired. If the event is canceled, the pipeline ends. +- `Block#attack` is called. + +#### The "Mining" Stage + +- `PlayerInteractEvent.LeftClickBlock` is fired. If the event is canceled, the pipeline moves to the "finishing" stage. +- `Block#getDestroyProgress` is called and added to the internal destroy progress counter. + - `Block#getDestroyProgress` returns a float value between 0 and 1, representing how much the destroy progress counter should be increased every tick. +- The progress overlay (cracking texture) is updated accordingly. +- If the destroy progress is greater than 1.0 (i.e. completed, i.e. the block should be broken), the "mining" stage is exited and the "actually breaking" stage is entered. + +#### The "Actually Breaking" Stage + +- `Item#onBlockStartBreak` is called. If it returns `true`, the pipeline moves to the "finishing" stage. +- Server-only: `IForgeBlock#canHarvestBlock` is called. +- `Block#playerWillDestroy` is called. +- The blockstate is removed from the level via a `Level#setBlock` call with `Blocks.AIR.defaultBlockState()` as the blockstate parameter. + - In that `Level#setBlock` call, `Block#onRemove` is called. +- `Block#destroy` is called. +- Server-only: If the previous call to `IForgeBlock#canHarvestBlock` returned `true`, `Block#playerDestroy` is called. +- Server-only: `Block#popExperience` is called. + +#### The "Finishing" Stage + +- The internal destroy progress counter is reset. + +### Ticking and Random Ticking + +Like many other things, blocks are ticked (updated) every tick, which is 1 / 20 of a second, or 50 milliseconds. + +There are two methods for ticking: `Block#tick` and `Block#animateTick`. The difference is that `Block#tick` is called only on the server, whereas `Block#animateTick` is called only on the client. For example, redstone updates are processed in `Block#tick`, while the fire particles of torches are spawned in `Block#animateTick`. Override either of them to add your server/client ticking behavior. + +Alongside ticking, there is a separate "weather tick", if you will. The method `Block#handlePrecipitation` is called only on the server, only when it is raining in some form, with a 1 in 16 chance. This is used for example by cauldrons that fill during rain or snowfall. + +And finally, there is the random tick system. Random ticks must be enabled through the `BlockBehaviour.Properties` of the block by calling the `BlockBehaviour.Properties#randomTicks()` method. This enables the block to be part of the random ticking mechanic. + +Random ticks occur every tick for a set amount of blocks in a chunk. That set amount is defined through the `randomTickSpeed` gamerule. With its default value of 3, every tick, 3 random blocks from the chunk are chosen. If these blocks have random ticking enabled, then their respective `Block#randomTick` methods are called. + +Random ticking is used by a wide range of mechanics in Minecraft, such as plant growth, ice and snow melting, or copper oxidizing. [blockentities]: ../blockentities/index.md +[blockreference]: reference.md#block [blockstates]: states.md +[events]: ../concepts/events.md +[interactionpipeline]: ../items/interactionpipeline.md [item]: ../items/index.md -[reference_properties]: reference.md#blockbehaviourproperties -[reference_block]: reference.md#block +[propertiesreference]: reference.md#blockbehaviourproperties [registration]: ../concepts/registries.md#methods-for-registering [resources]: ../resources/client/index.md [sounds]: ../gameeffects/sounds.md diff --git a/docs/blocks/reference.md b/docs/blocks/reference.md index 923f4a2a2..8b06d10cd 100644 --- a/docs/blocks/reference.md +++ b/docs/blocks/reference.md @@ -43,97 +43,97 @@ Some of these methods are actually located in `BlockBehaviour`, the abstract sup For methods with a `BlockState` parameter, it can be generally assumed that the given blockstate is a state of this block (unless stated otherwise). ::: -| Method | Description | -|---------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `protected void createBlockStateDefinition(StateDefinition.Builder)` | Defines the block state properties this block has. See [Implementing Blockstates][implementingblockstates] for more information. | -| `public StateDefinition getStateDefinition()` | Returns the blockstate definition. Used in a variety of internal places, such as the blockstate parser for commands. | -| `protected final void registerDefaultState(BlockState)` | Registers the default blockstate for this block. Should be called from the block constructor. | -| `public final BlockState defaultBlockState()` | Returns the default blockstate for this block. | -| `public final BlockState withPropertiesOf(BlockState)` | Copies the properties from the given blockstate to this block's default blockstate. This can be a blockstate belonging to a different block, in which case only the properties present on both will be copied. For example, this can be used to copy the rotation and slope properties of a regular rail to a powered rail. | -| `public FluidState getFluidState(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getFluidState` instead.** Returns the fluid state of this block. Returns `Fluids.EMPTY.defaultFluidState()` by default. Waterloggable blocks override this to return `Fluids.WATER.defaultFluidState()` if their `waterlogged` property is set to `true`. | -| `public Item asItem()` | Returns the `BlockItem` associated with the block, or `null` if no item is associated. | -| `protected Block asBlock()` | Helper for the abstract `BlockBehaviour` superclass to cast itself to `Block` where needed. | -| `public ItemStack getCloneItemStack(Level, BlockPos, BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Called when the player uses Pick Block (middle mouse button) in creative mode. Typically returns an `ItemStack` containing this block's associated `BlockItem`. Overridden by some blocks; for example, flower pots return the containing plant item here if available. | -| `public String toString()` | Returns the string representation of this block. Format is `"Block{namespace:path}"`, so for example for the block `"minecraft:cobblestone"`, this would be `"Block{minecraft:cobblestone}".` | -| `public String getDescriptionId()` | Returns this block's description ID, a.k.a. translation key. Has the format `"block.."`. For example, for the block `"minecraft:cobblestone"`, this returns `"block.minecraft.cobblestone"`. | -| `public MutableComponent getName()` | Returns a component containing this block's display name, using the translation key. | -| `protected boolean isAir(BlockState)` | Returns whether the given blockstate is air or not, set in `BlockBehaviour.Properties`. | -| `public MapColor defaultMapColor()` | Returns the `MapColor` of the default block state. | -| `public float defaultDestroyTime()` | Returns the destroy speed of the default block state. | -| `public float getExplosionResistance()` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns this block's explosion resistance, as set for this block in `BlockBehaviour.Properties`. | -| `public SoundType getSoundType(BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns the sound type set in `BlockBehaviour.Properties`. | -| `public float getFriction()` | Returns the friction value set in `BlockBehaviour.Properties`. | -| `public float getSpeedFactor()` | Returns the speed factor set in `BlockBehaviour.Properties`. | -| `public float getJumpFactor()` | Returns the jump factor set in `BlockBehaviour.Properties`. | -| `public float getMaxHorizontalOffset()` | Returns the max horizontal offset for blocks with random offset. Default value is 0.25, Pointed Dripstone overrides this to 0.125. See `BlockBehaviour.Properties#offsetType` for more information. | -| `public float getMaxVerticalOffset()` | Returns the max vertical offset for blocks with random offset. Default value is 0.2, Small Dripleaf overrides this to 0.1. See `BlockBehaviour.Properties#offsetType` for more information. | -| `public FeatureFlagSet requiredFeatures()` | Returns the required features set in `BlockBehaviour.Properties`. | -| `public boolean hasDynamicShape()` | Returns whether the block has a dynamic shape or not, as set in `BlockBehaviour.Properties`. | -| `public boolean isRandomlyTicking(BlockState)` | Returns whether the block can be randomly ticked or not, as set in `BlockBehaviour.Properties`. | -| `public final ResourceLocation getLootTable()` | Returns the loot table of the block, set in `BlockBehaviour.Properties`. | -| `public void tick(BlockState, ServerLevel, BlockPos, RandomSource)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#tick` instead.** Performs a tick (update) on the blockstate. This is called every tick (1 / 20 seconds). Does nothing by default. For example, chests and chest-like blocks check if the player is still in range for them to stay opened here, and redstone updates are performed here as well. | -| `public void randomTick(BlockState, ServerLevel, BlockPos, RandomSource)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#randomTick` instead.** Performs a random tick on the blockstate. For example, plants grow here, snow and ice melt here, and copper oxidizes here. The default implementation calls `Block#tick(BlockState, ServerLevel, BlockPos, RandomSource)`. | -| `public void animateTick(BlockState, Level, BlockPos, RandomSource)` | Called every tick (1 / 20 seconds) on the client side. Does nothing by default, but is overridden by several classes for client side effects, for example torch flame particles. | -| `public void handlePrecipitation(BlockState, Level, BlockPos, Biome.Precipitation)` | Called every tick (1 / 20 seconds) with a 1 in 16 chance when it is raining to handle weather-dependent behavior. | -| `public BlockState canBeReplaced(BlockState, BlockPlaceContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canBeReplaced` instead.** Returns whether the state can be replaced by another block. Returns `false` if the `replaceable` field in `BlockBehaviour.Properties` is `false` or if the blockstate being placed is the same as the given blockstate (since you obviously cannot replace grass with grass), and `true` if neither of those apply. Overridden by some blocks, mainly decorative blocks, for various additions to that rule. | -| `public BlockState canBeReplaced(BlockState, Fluid)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canBeReplaced` instead.** Variant of `#canBeReplaced(BlockState, BlockPlaceContext)` that is called when a block would be replaced by a fluid. Returns `false` if the `replaceable` field in `BlockBehaviour.Properties` is `false` or if the given blockstate is not solid, and `true` otherwise. Overridden by end portals and end gateways to always return `false`. | -| `public BlockState getStateForPlacement(BlockPlaceContext)` | Called when trying to place a `BlockItem` of this block down. The given `BlockPlaceContext` contains information such as the level, the position, the player, the stack and many more that can be used to determine the result. Returns the default block state, but is overridden in a wide range of places. For example, fences use this method to connect to other blocks when placing. | -| `public void onPlace(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onPlace` instead.** Called when the blockstate is placed. Parameter order is `state, level, position, oldStateAtThatPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Overridden in several places, mostly for performing post-placement behavior. | -| `public void setPlacedBy(Level, BlockPos, BlockState, @Nullable LivingEntity, ItemStack)` | Called **after** the blockstate has been placed down by the given `LivingEntity`. Overridden for example by player heads to fetch the associated player skin. | -| `public boolean canSurvive(BlockState, LevelReader, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canSurvive` instead.** Returns whether the blockstate can survive here or not. Returns `true` by default. Overridden by various blocks that have placement requirements, for example plants that need to check if they are placed on the correct soil, or hanging lanterns that check if they are actually still hanging. | -| `public BlockState rotate(BlockState, Rotation)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#rotate` instead.** Returns the state to use after rotating the block with the given rotation. Returns the given state by default. Overridden by all blocks with a `facing` property to consider said `facing` property. | -| `public BlockState mirror(BlockState, Mirror)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#mirror` instead.** Returns the state to use after mirroring the block with the given mirror. Returns the given state by default. Overridden by all blocks with a `facing` property to consider said `facing` property. | -| `public InteractionResult use(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#use` instead.** Called as part of the [Interaction Pipeline][interactionpipeline] when a block is activated or used. For example, this is where pressing a button or opening a crafting table GUI happens. For details on when exactly this is called and what to use as the return value, please refer to the [explanation of `Block#use` in the Interaction Pipeline article][blockuse]. | -| `public boolean triggerEvent(BlockState, Level, BlockPos, int, int)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#triggerEvent` instead.** Called on the server when `Level#blockEvent` is called. Called on the client as well if it returned `true` on the server. The primary use of this mechanic is to notify the other side of changes that cannot be sent via a block entity. The type of event is identified by the id parameter (first `int` parameter). Additional info can be passed into the second `int` parameter. For example, pistons use the second `int` parameter to specify the direction, and shulker boxes use the second parameter for specifying how many players are currently accessing the shulker box. | -| `public MenuProvider getMenuProvider(BlockState, Level, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getMenuProvider` instead.** Returns a menu provider to show when right-clicking the block. Returns `null` by default. Overridden by blocks that don't have a `BlockEntity` but still have a GUI, such as the Crafting Table, the Smithing Table or the Grindstone. | -| `public void attack(BlockState, ServerLevel, BlockPos, Player)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#attack` instead.** Called when a player begins breaking the block. For example, note blocks play their note here, and the dragon egg teleports away. The default implementation is empty. | -| `public void onProjectileHit(Level, BlockState, BlockHitResult, Projectile)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onProjectileHit` instead.** Called when a `Projectile` (for example an arrow or a fireball) hits the blockstate. Does nothing by default. For example, TNT ignites itself here when hit with a burning projectile. | -| `public void playerWillDestroy(Level, BlockPos, BlockState, Player)` | Called immediately **before** the blockstate will be destroyed by the given player. Called regardless of whether the player is using the correct tool. By default, this spawns breaking particles and angers piglins if applicable. Overridden in various places for additional behavior, for example by doors to break their upper/lower part as well. | -| `public void onRemove(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onRemove` instead.** Called when the blockstate is removed. Parameter order is `state, level, position, newStateAtThatPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Default behavior removes a block entity present at the position from the level, if applicable. Overridden in several places, mostly to either spill out container content or to perform a final redstone update. | -| `public void destroy(LevelAcccessor, BlockPos, BlockState)` | Called **after** the blockstate has been destroyed by the player. Used by pistons to destroy the piston head as well if they are activated. | -| `public void playerDestroy(Level, Player, BlockPos, BlockState, @Nullable BlockEntity, ItemStack)` | Called **after** the given player has destroyed the given blockstate with the given tool at the given position in the given level. Called only if the block has used a sufficient tool for drops to spawn, so for example, this will not be called when breaking diamond ore with a wooden pickaxe. Default behaviour handles resource dropping. Overridden for example by beehives that spawn bees in this method when destroyed. | -| `protected void spawnDestroyParticles(Level, Player, BlockPos, BlockState)` | Sends a packet to the client to spawn breaking particles there. Overridden to no-op by fire blocks. | -| `public List getDrops(BlockState, LootParams.Builder)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getDrops` instead.** Rolls the loot table for the block with blockstate context. Overridden by some blocks that add custom modifications to the results, such as shulker boxes that add their inventory to the dropped `ItemStack`. | -| `public void popExperience(ServerLevel, BlockPos, int)` | Drops the given amount of experience in the given level at the given position. Respects the `doTileDrops` gamerule. | -| `protected void tryDropExperience(ServerLevel, BlockPos, ItemStack, IntProvider)` | Helper method for dropping experience if the given `ItemStack` is not enchanted with Silk Touch. Currently unused. | -| `public void spawnAfterBreak(BlockState, ServerLevel, BlockPos, ItemStack, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#spawnAfterBreak` instead.** Spawns entities after breaking this blockstate. The `boolean` parameter determines whether to drop experience or not. The default implementation drops experience if the `boolean` parameter is `true` and `Block#getExpDrop` returns more than 0. Overridden by ore blocks and spawners to drop xp, and by infested blocks to spawn silverfish. | -| `public void dropFromExplosion(Explosion)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Whether this block should drop when destroyed by an explosion. `true` by default, overridden to return `false` for TNT. | -| `public void wasExploded(Level, BlockPos, Explosion)` | Called **after** the blockstate has been destroyed by an explosion. | -| `public void stepOn(Level, BlockPos, BlockState, Entity)` | Called when an entity stands on this blockstate. Used for example by magma blocks to apply magma damage. | -| `public void entityInside(BlockState, ServerLevel, BlockPos, Entity)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#entityInside` instead.** Called when the given entity is inside this blockstate. Does nothing by default. For example, fire blocks ignite entities that stand in them here. | -| `public void fallOn(Level, BlockState, BlockPos, Entity, float)` | Called when an entity falls onto this blockstate from the given distance. Default behavior is to cause fall damage. Overridden by various blocks that modify fall damage, for example beds or pointed dripstone. | -| `public void updateEntityAfterFallOn(Level, Entity)` | Called **after** an entity falls onto this block and `#fallOn` has already been called. This method is mainly responsible for handling the given entity's movement after falling on the block. Default behavior is to cancel any vertical movement. Overridden by beds and slime blocks to perform their bouncing behavior. | -| `public boolean propagatesSkylightDown(BlockState, BlockGetter, BlockPos)` | Whether this block propagates skylight through itself or not. By default, this returns `true` if the block is not a full block and has no fluid state. However, this is overridden by several blocks, such as glass which always lets light pass through it. | -| `public boolean skipRendering(BlockState, BlockState, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#skipRendering` instead.** Whether this block's rendering should be skipped or not, given the context of the adjacent blockstate (second `BlockState` parameter). Used for example by glass to not render itself over and over in a glass layer that's several blocks wide. | -| `public RenderShape getRenderShape(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getRenderShape` instead.** Defines how the block should be rendered. Possible values are `RenderShape.ENTITYBLOCK_ANIMATED` for blocks that use a [`BlockEntityRenderer`][ber], `RenderShape.MODEL` if a JSON model or a mix of JSON model and `BlockEntityRenderer` is used, and `RenderShape.INVISIBLE` to not render at all. The default value is `RenderShape.MODEL`. | -| `public VoxelShape getShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getShape` instead.** Returns the block's selection shape. Returns a 1x1x1 block shape by default. Overridden by blocks that have a non-1x1x1 shape, for example slabs, stairs, walls, fences, carpets, beds and many many others. | -| `public VoxelShape getBlockSupportShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getBlockSupportShape` instead.** Returns the shape to use when checking if this block can support another block. Returns the collision shape by default. Overridden by some blocks with unusual collision shapes, for example soul sand or mud, to still support blocks on top of them. | -| `public VoxelShape getInteractionShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getInteractionShape` instead.** Returns the shape to use for special interactions with this block. Returns an empty shape by default. Overridden by blocks that have different interactions depending on the side used, for example hoppers or cauldrons. | -| `public VoxelShape getVisualShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getVisualShape` instead.** Returns what is considered the block's visual shape. Returns the collision shape by default. Overridden by some blocks that consider the visual shape to be the selection shape, such as fences and iron bars. | -| `public VoxelShape getCollisionShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getCollisionShape` instead.** Returns the block's collision shape, a.k.a. hitbox. Returns the selection shape if collision is enabled (as set in the `BlockBehaviour.Properties`) and an empty shape if not. Overridden by blocks where the selection shape is different from the collision shape, such as walls, fence gates, lecterns or soul sand. | -| `public VoxelShape getOcclusionShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getOcclusionShape` instead.** Returns the shape to use for occlusion by the light engine. Returns the normal shape by default. Overridden by some blocks, for example fences or lecterns, to return a smaller shape. | -| `public boolean isCollisionShapeFullBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isCollisionShapeFullBlock` instead.** Returns `true` if the block's collision shape is a full block, `false` if not. | -| `public boolean isOcclusionShapeFullBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isOcclusionShapeFullBlock` instead.** Returns `true` if the block's occlusion shape is a full block, `false` if not. | -| `public boolean useShapeForLightOcclusion(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#useShapeForLightOcclusion` instead.** Whether the block should use its shape for light occlusion or not. Returns `false` by default, but is overridden to `true` by many blocks that don't have a full block shape, such as slabs, stairs or sculk sensors. | -| `public int getLightBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getLightBlock` instead.** Returns how much the block blocks light. Returns 15 for solid blocks, 0 if `Block#propagatesSkylightDown(Level, BlockPos)` returns `true`, and 1 otherwise. Overridden to be 15 by Tinted Glass, despite being a non-solid block. | -| `public float getShadeBrightness(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getShadeBrightness` instead.** Returns the shade brightness of this block, used by the light engine. Returns 0.2 for solid blocks and 1.0 for all other blocks by default. Overridden by some blocks with unusual collision shapes, for example soul sand or mud, to still act like a solid block in this situation. | -| `public boolean updateShape(BlockState, Direction, BlockState, LevelAccessor, BlockPos, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#updateShape` instead.** Updates the blockstate given the neighbor context. Parameter order is `ownState, neighborDirection, neighborState, level, ownPosition, neighborPosition`. Returns itself by default, overridden in a lot of places, for example by fences, walls or blocks that are attached to another block. | -| `public void updateIndirectNeighbourShapes(BlockState, BlockGetter, BlockPos, int, int)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#updateIndirectNeighbourShapes` instead.** Updates the diagonal neighbor blockstates. The `int` parameters are the flags and worldgen recursion values, see `Block.updateOrDestroy` for a more detailed explanation of those. Does nothing by default, but is overridden by redstone wires. | -| `public boolean neighborChanged(BlockState, Level, BlockPos, Block, BlockPos, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#neighborChanged` instead.** Called when a neighboring block has been changed. Parameter order is `state, level, fromPosition, movedBlock, toPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Overridden in several places, mostly with some relation to redstone. | -| `protected ImmutableMap getShapeForEachState(Function)` | Used by the internal shape cache for blockstate-specific shapes. Overridden by big dripleaves to handle the "falling through" when tilting. | -| `public long getSeed(BlockState, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getSeed` instead.** Returns a seed to use when randomly selecting one of multiple possible models. | -| `public boolean hasAnalogOutputSignal(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#hasAnalogOutputSignal` instead.** Whether this block has a redstone output signal that comparators can listen to. This is not saying that the block always emits a redstone signal. To get the actually emitted redstone signal, use `Block#getAnalogOutputSignal`. | -| `public int getAnalogOutputSignal(BlockState, Level, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getAnalogOutputSignal` instead.** Returns the analog redstone value emitted by this block, which can be read by comparators. Returns 0 by default. Overridden by various containers and redstone components to return their redstone signal value, for example a value from 0 to 15 by hoppers. This does not return the redstone power value of the block itself, see `Block#getSignal` for that. | -| `public int getSignal(BlockState, ServerLevel, BlockPos, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getSignal` instead.** Returns the **outgoing** redstone signal strength of the block in the given direction. Returns 0 by default. For example, this would return 15 for an activated lever and 0 for a deactivated lever. | -| `public int getDirectSignal(BlockState, ServerLevel, BlockPos, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getDirectSignal` instead.** Returns the **incoming** redstone signal strength of the block from the given direction. Returns 0 by default. Overridden by blocks that only accept redstone power if it comes from the correct side, such as redstone torches. | -| `public boolean isSignalSource(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isSignalSource` instead.** Whether the block is a signal source. Note that vanilla doesn't actually use this a lot, only checking it in redstone wires and rails and overriding it to unconditionally return `true` in a lot of places where it does not actually make sense. This is because most of the time, vanilla simply checks the `powered` blockstate property instead. | -| `public boolean isPathfindable(BlockState, BlockGetter, BlockPos, PathComputationType)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isPathfindable` instead.** Whether mobs can pathfind over the blockstate or not. Default behavior checks for a full block, or for water if the PathComputationType is `WATER`. Overridden to `false` in a variety of places, for example soul sand, respawn anchors or various non-full blocks, just to be sure. | -| `public boolean isPossibleToRespawnInThis(BlockState)` | Whether respawning in this blockstate is possible or not. Default behaviour is to return `true` if the blockstate is not solid and not a liquid. Overridden by banners, pressure plates and signs to return `true` despite being solid. | -| `public void appendHoverText(ItemStack, @Nullable BlockGetter, List, TooltipFlag)` | Called by the method of the same name in `Item`, this method is responsible for appending hover texts (tooltips) to the item. Does nothing by default. Overridden for example by shulker boxes that add their content tooltips here. | -| `public Holder.Reference builtInRegistryHolder()` | **DEPRECATED.** Internal reference to the builtin block registry holder. **Do not use this, use one of the safer equivalents in `ForgeRegistries.BLOCKS` instead, for example `#getDelegateOrThrow`.** | -| `public Object getRenderPropertiesInternal()` | **DEPRECATED FOR REMOVAL: There is no need for you to use this!** If you are using this somewhere in legacy code, ask in the Discord on how to replace this. NeoForge-added. | -| `public void initializeClient(Consumer consumer)` | Allows for adding custom client-side behavior in the form of a class implementing `IClientBlockExtensions`. NeoForge-added. | -| `public boolean canSustainPlant(BlockState, BlockGetter, BlockPos, Direction, IPlantable)` | Whether this blockstate can sustain the given plant, in the form of an `IPlantable`. Note that this system is flawed and will likely be replaced with a better system in the future. NeoForge-added. | +| Method | Description | +|---------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `protected void createBlockStateDefinition(StateDefinition.Builder)` | Defines the block state properties this block has. See [Implementing Blockstates][implementingblockstates] for more information. | +| `public StateDefinition getStateDefinition()` | Returns the blockstate definition. Used in a variety of internal places, such as the blockstate parser for commands. | +| `protected final void registerDefaultState(BlockState)` | Registers the default blockstate for this block. Should be called from the block constructor. | +| `public final BlockState defaultBlockState()` | Returns the default blockstate for this block. | +| `public final BlockState withPropertiesOf(BlockState)` | Copies the properties from the given blockstate to this block's default blockstate. This can be a blockstate belonging to a different block, in which case only the properties present on both will be copied. For example, this can be used to copy the rotation and slope properties of a regular rail to a powered rail. | +| `public FluidState getFluidState(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getFluidState` instead.** Returns the fluid state of this block. Returns `Fluids.EMPTY.defaultFluidState()` by default. Waterloggable blocks override this to return `Fluids.WATER.defaultFluidState()` if their `waterlogged` property is set to `true`. | +| `public Item asItem()` | Returns the `BlockItem` associated with the block, or `null` if no item is associated. | +| `protected Block asBlock()` | Helper for the abstract `BlockBehaviour` superclass to cast itself to `Block` where needed. | +| `public ItemStack getCloneItemStack(Level, BlockPos, BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Called when the player uses Pick Block (middle mouse button) in creative mode. Typically returns an `ItemStack` containing this block's associated `BlockItem`. Overridden by some blocks; for example, flower pots return the containing plant item here if available. | +| `public String toString()` | Returns the string representation of this block. Format is `"Block{namespace:path}"`, so for example for the block `"minecraft:cobblestone"`, this would be `"Block{minecraft:cobblestone}".` | +| `public String getDescriptionId()` | Returns this block's description ID, a.k.a. translation key. Has the format `"block.."`. For example, for the block `"minecraft:cobblestone"`, this returns `"block.minecraft.cobblestone"`. | +| `public MutableComponent getName()` | Returns a component containing this block's display name, using the translation key. | +| `protected boolean isAir(BlockState)` | Returns whether the given blockstate is air or not, set in `BlockBehaviour.Properties`. | +| `public MapColor defaultMapColor()` | Returns the `MapColor` of the default block state. | +| `public float defaultDestroyTime()` | Returns the destroy speed of the default block state. | +| `public float getExplosionResistance()` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns this block's explosion resistance, as set for this block in `BlockBehaviour.Properties`. | +| `public SoundType getSoundType(BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns the sound type set in `BlockBehaviour.Properties`. | +| `public float getFriction()` | Returns the friction value set in `BlockBehaviour.Properties`. | +| `public float getSpeedFactor()` | Returns the speed factor set in `BlockBehaviour.Properties`. | +| `public float getJumpFactor()` | Returns the jump factor set in `BlockBehaviour.Properties`. | +| `public float getMaxHorizontalOffset()` | Returns the max horizontal offset for blocks with random offset. Default value is 0.25, Pointed Dripstone overrides this to 0.125. See `BlockBehaviour.Properties#offsetType` for more information. | +| `public float getMaxVerticalOffset()` | Returns the max vertical offset for blocks with random offset. Default value is 0.2, Small Dripleaf overrides this to 0.1. See `BlockBehaviour.Properties#offsetType` for more information. | +| `public FeatureFlagSet requiredFeatures()` | Returns the required features set in `BlockBehaviour.Properties`. | +| `public boolean hasDynamicShape()` | Returns whether the block has a dynamic shape or not, as set in `BlockBehaviour.Properties`. | +| `public boolean isRandomlyTicking(BlockState)` | Returns whether the block can be randomly ticked or not, as set in `BlockBehaviour.Properties`. | +| `public final ResourceLocation getLootTable()` | Returns the loot table of the block, set in `BlockBehaviour.Properties`. | +| `public void tick(BlockState, ServerLevel, BlockPos, RandomSource)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#tick` instead.** Performs a server tick on the blockstate. Does nothing by default. See [block ticking][blocktick] for more information. | +| `public void randomTick(BlockState, ServerLevel, BlockPos, RandomSource)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#randomTick` instead.** Performs a random tick on the blockstate. The default implementation calls `Block#tick(BlockState, ServerLevel, BlockPos, RandomSource)`. See [block ticking][blocktick] for more information. | +| `public void animateTick(BlockState, Level, BlockPos, RandomSource)` | Performs a client tick on the blockstate. Does nothing by default. See [block ticking][blocktick] for more information. | +| `public void handlePrecipitation(BlockState, Level, BlockPos, Biome.Precipitation)` | Performs a weather tick on the blockstate. Does nothing by default. See [block ticking][blocktick] for more information. | +| `public BlockState canBeReplaced(BlockState, BlockPlaceContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canBeReplaced` instead.** Returns whether the state can be replaced by another block. Returns `false` if the `replaceable` field in `BlockBehaviour.Properties` is `false` or if the blockstate being placed is the same as the given blockstate (since you obviously cannot replace grass with grass), and `true` if neither of those apply. Overridden by some blocks, mainly decorative blocks, for various additions to that rule. See the [block placement pipeline][blockplace] for more information. | +| `public BlockState canBeReplaced(BlockState, Fluid)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canBeReplaced` instead.** Variant of `#canBeReplaced(BlockState, BlockPlaceContext)` that is called when a block would be replaced by a fluid. Returns `false` if the `replaceable` field in `BlockBehaviour.Properties` is `false` or if the given blockstate is not solid, and `true` otherwise. Overridden by end portals and end gateways to always return `false`. See the [block placement pipeline][blockplace] for more information. | +| `public BlockState getStateForPlacement(BlockPlaceContext)` | Called when trying to place a `BlockItem` of this block down. The given `BlockPlaceContext` contains information such as the level, the position, the player, the stack and many more that can be used to determine the result. Returns the default block state, but is overridden in a wide range of places. For example, fences use this method to connect to other blocks when placing. See the [block placement pipeline][blockplace] for more information. | +| `public void onPlace(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onPlace` instead.** Called when the blockstate is placed. Parameter order is `state, level, position, oldStateAtThatPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Overridden in several places, mostly for performing post-placement behavior. See the [block placement pipeline][blockplace] for more information. | +| `public void setPlacedBy(Level, BlockPos, BlockState, @Nullable LivingEntity, ItemStack)` | Called **after** the blockstate has been placed down by the given `LivingEntity`. Overridden for example by player heads to fetch the associated player skin. See the [block placement pipeline][blockplace] for more information. | +| `public boolean canSurvive(BlockState, LevelReader, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canSurvive` instead.** Returns whether the blockstate can survive here or not. Returns `true` by default. Overridden by various blocks that have placement requirements, for example plants that need to check if they are placed on the correct soil, or hanging lanterns that check if they are actually still hanging. See the [block placement pipeline][blockplace] for more information. | +| `public BlockState rotate(BlockState, Rotation)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#rotate` instead.** Returns the state to use after rotating the block with the given rotation. Returns the given state by default. Overridden by all blocks with a `facing` property to consider said `facing` property. | +| `public BlockState mirror(BlockState, Mirror)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#mirror` instead.** Returns the state to use after mirroring the block with the given mirror. Returns the given state by default. Overridden by all blocks with a `facing` property to consider said `facing` property. | +| `public InteractionResult use(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#use` instead.** Called as part of the [Interaction Pipeline][interactionpipeline] when a block is activated or used. For example, this is where pressing a button or opening a crafting table GUI happens. For details on when exactly this is called and what to use as the return value, please refer to the [explanation of `Block#use` in the Interaction Pipeline article][blockuse]. | +| `public boolean triggerEvent(BlockState, Level, BlockPos, int, int)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#triggerEvent` instead.** Called on the server when `Level#blockEvent` is called. Called on the client as well if it returned `true` on the server. The primary use of this mechanic is to notify the other side of changes that cannot be sent via a block entity. Currently, this is only used by comparators. | +| `public MenuProvider getMenuProvider(BlockState, Level, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getMenuProvider` instead.** Returns a menu provider to show when right-clicking the block. Returns `null` by default. Overridden by blocks that don't have a `BlockEntity` but still have a GUI, such as the Crafting Table, the Smithing Table or the Grindstone. | +| `public void attack(BlockState, ServerLevel, BlockPos, Player)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#attack` instead.** Called when a player begins breaking the block. For example, note blocks play their note here, and the dragon egg teleports away. The default implementation is empty. See the [block breaking pipeline][blockbreak] for more information. | +| `public void playerWillDestroy(Level, BlockPos, BlockState, Player)` | Called immediately **before** the blockstate will be destroyed by the given player. Called regardless of whether the player is using the correct tool. By default, this spawns breaking particles and angers piglins if applicable. Overridden in various places for additional behavior, for example by doors to break their upper/lower part as well. See the [block breaking pipeline][blockbreak] for more information. | +| `protected void spawnDestroyParticles(Level, Player, BlockPos, BlockState)` | Called by `Block#playerWillDestroy`. Sends a packet to the client to spawn breaking particles there. Overridden to no-op by fire blocks. | +| `public void onRemove(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onRemove` instead.** Called during blockstate removal. Parameter order is `state, level, position, newStateAtThatPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Default behavior removes a block entity present at the position from the level, if applicable. Overridden in several places, mostly to either spill out container content or to perform a final redstone update. See the [block breaking pipeline][blockbreak] for more information. | +| `public void destroy(LevelAcccessor, BlockPos, BlockState)` | Called immediately **after** the blockstate has been destroyed by the player. Used by pistons to destroy the piston head as well if they are activated. See the [block breaking pipeline][blockbreak] for more information. | +| `public void playerDestroy(Level, Player, BlockPos, BlockState, @Nullable BlockEntity, ItemStack)` | Called **after** the given player has destroyed the given blockstate with the given tool at the given position in the given level. Called only on the server side, and only if the block has used a sufficient tool for drops to spawn, so for example, this will not be called when breaking diamond ore with a wooden pickaxe. Default behaviour handles resource dropping. Overridden for example by beehives that spawn bees in this method when destroyed. See the [block breaking pipeline][blockbreak] for more information. | +| `public void popExperience(ServerLevel, BlockPos, int)` | Drops the given amount of experience in the given level at the given position. Called only on the server side. Respects the `doTileDrops` gamerule. See the [block breaking pipeline][blockbreak] for more information. | +| `protected void tryDropExperience(ServerLevel, BlockPos, ItemStack, IntProvider)` | Helper method for dropping experience if the given `ItemStack` is not enchanted with Silk Touch. Currently unused. | +| `public List getDrops(BlockState, LootParams.Builder)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getDrops` instead.** Called by the static `Block.getDrops` methods. Rolls the loot table for the block with blockstate context. Overridden by some blocks that add custom modifications to the results, such as shulker boxes that add their inventory to the dropped `ItemStack`. | +| `public void spawnAfterBreak(BlockState, ServerLevel, BlockPos, ItemStack, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#spawnAfterBreak` instead.** Spawns entities after breaking this blockstate. The `boolean` parameter determines whether to drop experience or not. The default implementation drops experience if the `boolean` parameter is `true` and `Block#getExpDrop` returns more than 0. Overridden by ore blocks and spawners to drop xp, and by infested blocks to spawn silverfish. | +| `public void dropFromExplosion(Explosion)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Whether this block should drop when destroyed by an explosion. `true` by default, overridden to return `false` for TNT. | +| `public void wasExploded(Level, BlockPos, Explosion)` | Called **after** the blockstate has been destroyed by an explosion. | +| `public void stepOn(Level, BlockPos, BlockState, Entity)` | Called when an entity stands on this blockstate. Used for example by magma blocks to apply magma damage. | +| `public void entityInside(BlockState, ServerLevel, BlockPos, Entity)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#entityInside` instead.** Called when the given entity is inside this blockstate. Does nothing by default. For example, fire blocks ignite entities that stand in them here. | +| `public void fallOn(Level, BlockState, BlockPos, Entity, float)` | Called when an entity falls onto this blockstate from the given distance. Default behavior is to cause fall damage. Overridden by various blocks that modify fall damage, for example beds or pointed dripstone. | +| `public void updateEntityAfterFallOn(Level, Entity)` | Called **after** an entity falls onto this block and `#fallOn` has already been called. This method is mainly responsible for handling the given entity's movement after falling on the block. Default behavior is to cancel any vertical movement. Overridden by beds and slime blocks to perform their bouncing behavior. | +| `public void onProjectileHit(Level, BlockState, BlockHitResult, Projectile)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onProjectileHit` instead.** Called when a `Projectile` (for example an arrow or a fireball) hits the blockstate. Does nothing by default. For example, TNT ignites itself here when hit with a burning projectile. | +| `public boolean propagatesSkylightDown(BlockState, BlockGetter, BlockPos)` | Whether this block propagates skylight through itself or not. By default, this returns `true` if the block is not a full block and has no fluid state. However, this is overridden by several blocks, such as glass which always lets light pass through it. | +| `public boolean skipRendering(BlockState, BlockState, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#skipRendering` instead.** Whether this block's rendering should be skipped or not, given the context of the adjacent blockstate (second `BlockState` parameter). Used for example by glass to not render itself over and over in a glass layer that's several blocks wide. | +| `public RenderShape getRenderShape(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getRenderShape` instead.** Defines how the block should be rendered. Possible values are `RenderShape.ENTITYBLOCK_ANIMATED` for blocks that use a [`BlockEntityRenderer`][ber], `RenderShape.MODEL` if a JSON model or a mix of JSON model and `BlockEntityRenderer` is used, and `RenderShape.INVISIBLE` to not render at all. The default value is `RenderShape.MODEL`. | +| `public VoxelShape getShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getShape` instead.** Returns the block's selection shape. Returns a 1x1x1 block shape by default. Overridden by blocks that have a non-1x1x1 shape, for example slabs, stairs, walls, fences, carpets, beds and many many others. | +| `public VoxelShape getBlockSupportShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getBlockSupportShape` instead.** Returns the shape to use when checking if this block can support another block. Returns the collision shape by default. Overridden by some blocks with unusual collision shapes, for example soul sand or mud, to still support blocks on top of them. | +| `public VoxelShape getInteractionShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getInteractionShape` instead.** Returns the shape to use for special interactions with this block. Returns an empty shape by default. Overridden by blocks that have different interactions depending on the side used, for example hoppers or cauldrons. | +| `public VoxelShape getVisualShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getVisualShape` instead.** Returns what is considered the block's visual shape. Returns the collision shape by default. Overridden by some blocks that consider the visual shape to be the selection shape, such as fences and iron bars. | +| `public VoxelShape getCollisionShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getCollisionShape` instead.** Returns the block's collision shape, a.k.a. hitbox. Returns the selection shape if collision is enabled (as set in the `BlockBehaviour.Properties`) and an empty shape if not. Overridden by blocks where the selection shape is different from the collision shape, such as walls, fence gates, lecterns or soul sand. | +| `public VoxelShape getOcclusionShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getOcclusionShape` instead.** Returns the shape to use for occlusion by the light engine. Returns the normal shape by default. Overridden by some blocks, for example fences or lecterns, to return a smaller shape. | +| `public boolean isCollisionShapeFullBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isCollisionShapeFullBlock` instead.** Returns `true` if the block's collision shape is a full block, `false` if not. | +| `public boolean isOcclusionShapeFullBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isOcclusionShapeFullBlock` instead.** Returns `true` if the block's occlusion shape is a full block, `false` if not. | +| `public boolean useShapeForLightOcclusion(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#useShapeForLightOcclusion` instead.** Whether the block should use its shape for light occlusion or not. Returns `false` by default, but is overridden to `true` by many blocks that don't have a full block shape, such as slabs, stairs or sculk sensors. | +| `public int getLightBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getLightBlock` instead.** Returns how much the block blocks light. Returns 15 for solid blocks, 0 if `Block#propagatesSkylightDown(Level, BlockPos)` returns `true`, and 1 otherwise. Overridden to be 15 by Tinted Glass, despite being a non-solid block. | +| `public float getShadeBrightness(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getShadeBrightness` instead.** Returns the shade brightness of this block, used by the light engine. Returns 0.2 for solid blocks and 1.0 for all other blocks by default. Overridden by some blocks with unusual collision shapes, for example soul sand or mud, to still act like a solid block in this situation. | +| `public boolean updateShape(BlockState, Direction, BlockState, LevelAccessor, BlockPos, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#updateShape` instead.** Updates the blockstate given the neighbor context. Parameter order is `ownState, neighborDirection, neighborState, level, ownPosition, neighborPosition`. Returns itself by default, overridden in a lot of places, for example by fences, walls or blocks that are attached to another block. | +| `public void updateIndirectNeighbourShapes(BlockState, BlockGetter, BlockPos, int, int)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#updateIndirectNeighbourShapes` instead.** Updates the diagonal neighbor blockstates. The `int` parameters are the flags and worldgen recursion values, see `Block.updateOrDestroy` for a more detailed explanation of those. Does nothing by default, but is overridden by redstone wires. | +| `public boolean neighborChanged(BlockState, Level, BlockPos, Block, BlockPos, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#neighborChanged` instead.** Called when a neighboring block has been changed. Parameter order is `state, level, fromPosition, movedBlock, toPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Overridden in several places, mostly with some relation to redstone. | +| `protected ImmutableMap getShapeForEachState(Function)` | Used by the internal shape cache for blockstate-specific shapes. Overridden by big dripleaves to handle the "falling through" when tilting. | +| `public long getSeed(BlockState, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getSeed` instead.** Returns a seed to use when randomly selecting one of multiple possible models. | +| `public boolean hasAnalogOutputSignal(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#hasAnalogOutputSignal` instead.** Whether this block has a redstone output signal that comparators can listen to. This is not saying that the block always emits a redstone signal. To get the actually emitted redstone signal, use `Block#getAnalogOutputSignal`. | +| `public int getAnalogOutputSignal(BlockState, Level, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getAnalogOutputSignal` instead.** Returns the analog redstone value emitted by this block, which can be read by comparators. Returns 0 by default. Overridden by various containers and redstone components to return their redstone signal value, for example a value from 0 to 15 by hoppers. This does not return the redstone power value of the block itself, see `Block#getSignal` for that. | +| `public int getSignal(BlockState, ServerLevel, BlockPos, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getSignal` instead.** Returns the **outgoing** redstone signal strength of the block in the given direction. Returns 0 by default. For example, this would return 15 for an activated lever and 0 for a deactivated lever. | +| `public int getDirectSignal(BlockState, ServerLevel, BlockPos, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getDirectSignal` instead.** Returns the **incoming** redstone signal strength of the block from the given direction. Returns 0 by default. Overridden by blocks that only accept redstone power if it comes from the correct side, such as redstone torches. | +| `public boolean isSignalSource(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isSignalSource` instead.** Whether the block is a signal source. Note that vanilla doesn't actually use this a lot, only checking it in redstone wires and rails and overriding it to unconditionally return `true` in a lot of places where it does not actually make sense. This is because most of the time, vanilla simply checks the `powered` blockstate property instead. | +| `public boolean isPathfindable(BlockState, BlockGetter, BlockPos, PathComputationType)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isPathfindable` instead.** Whether mobs can pathfind over the blockstate or not. Default behavior checks for a full block, or for water if the PathComputationType is `WATER`. Overridden to `false` in a variety of places, for example soul sand, respawn anchors or various non-full blocks, just to be sure. | +| `public boolean isPossibleToRespawnInThis(BlockState)` | Whether respawning in this blockstate is possible or not. Default behaviour is to return `true` if the blockstate is not solid and not a liquid. Overridden by banners, pressure plates and signs to return `true` despite being solid. | +| `public void appendHoverText(ItemStack, @Nullable BlockGetter, List, TooltipFlag)` | Called by the method of the same name in `Item`, this method is responsible for appending hover texts (tooltips) to the item. Does nothing by default. Overridden for example by shulker boxes that add their content tooltips here. | +| `public Holder.Reference builtInRegistryHolder()` | **DEPRECATED.** Internal reference to the builtin block registry holder. **Do not use this, use one of the safer equivalents in `ForgeRegistries.BLOCKS` instead, for example `#getDelegateOrThrow`.** | +| `public Object getRenderPropertiesInternal()` | **DEPRECATED FOR REMOVAL: There is no need for you to use this!** If you are using this somewhere in legacy code, ask in the Discord on how to replace this. NeoForge-added. | +| `public void initializeClient(Consumer consumer)` | Allows for adding custom client-side behavior in the form of a class implementing `IClientBlockExtensions`. NeoForge-added. | +| `public boolean canSustainPlant(BlockState, BlockGetter, BlockPos, Direction, IPlantable)` | Whether this blockstate can sustain the given plant, in the form of an `IPlantable`. Note that this system has found to be flawed and will likely be replaced with a better system in the future. NeoForge-added. | `BlockState` ------------ @@ -211,6 +211,8 @@ public static final Block OAK_PLANKS = register("oak_planks", new Block(BlockBeh | `requiredFeatures(FeatureFlag...)` | Sets the block's required feature flags. The block will only be actually registered if all the passed feature flags are activated. Currently unused, but historically used for bamboo and cherry wood (among others) when they were in their experimental phase. | [ber]: ../blockentities/ber.md +[blockbreak]: index.md#breaking-a-block +[blockplace]: index.md#breaking-a-block [blockuse]: ../items/interactionpipeline.md#blockuse [implementingblockstates]: states.md#implementing-blockstates [interactionpipeline]: ../items/interactionpipeline.md diff --git a/docs/blocks/states.md b/docs/blocks/states.md index 5f23b37bc..303683a64 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -25,7 +25,7 @@ minecraft:lever[facing=up,powered=true] minecraft:lever[facing=down,powered=true] ``` -The notation `blockid[property1=value1,property2=value,...]` is the standardized way of representing a blockstate in text form, and is used in some locations in vanilla, for example in commmands. +The notation `blockid[property1=value1,property2=value,...]` is the standardized way of representing a blockstate in text form, and is used in some locations in vanilla, for example in commands. If your block does not have any blockstate properties defined, it still has exactly one blockstate - that is the one without any properties, since there are no properties to specify. This can be denoted as `minecraft:oak_planks[]` or simply `minecraft:oak_planks`. @@ -47,7 +47,7 @@ Blockstates and block entities can be used in conjunction with one another. For Implementing Blockstates ------------------------ -To implement a blockstate property, in your block class, create or reference a `public static final Property` constant. While you are free to make your own `Property` implementations, the vanilla code provides several convenience implementations that should cover most usecases: +To implement a blockstate property, in your block class, create or reference a `public static final Property` constant. While you are free to make your own `Property` implementations, the vanilla code provides several convenience implementations that should cover most use cases: * `IntegerProperty` * Implements `Property`. Defines a property that holds an integer value. Note that negative values are not supported. @@ -103,6 +103,8 @@ public class LeverBlock extends Block { Using Blockstates ----------------- +To go from `Block` to `BlockState`, call `Block#defaultBlockState()`. + You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. Reusing our lever example, this would look something like `Direction direction = leverBlockState.getValue(LeverBlock.FACING);` If you want to get a `BlockState` with a different set of values, simply call `BlockState#setValue(Property, T)` on an existing block state with the property and its value. With our lever, this goes something like `leverBlockState = leverBlockState.setValue(LeverBlock.FACING, Direction.SOUTH);` From eeb617abe88d77869c0259a75588014ee94a3467 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 <52419336+IchHabeHunger54@users.noreply.github.com> Date: Sun, 22 Oct 2023 12:35:10 +0200 Subject: [PATCH 08/27] Update docs/blocks/index.md Co-authored-by: ChampionAsh5357 --- docs/blocks/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 97d2a6959..9658dc10c 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -1,7 +1,7 @@ Blocks ====== -Blocks are, obviously, essential to the Minecraft world. They make up all the terrain, structures, and machines. Chances are if you are interested in making a mod, then you will want to add some blocks. This page will guide you through the creation of blocks, and some of the things you can do with them. +Blocks are essential to the Minecraft world. They make up all the terrain, structures, and machines. Chances are if you are interested in making a mod, then you will want to add some blocks. This page will guide you through the creation of blocks, and some of the things you can do with them. One Block to Rule Them All -------------------------- From d2b5bd0f9332e18e3322324265fb657204db07c7 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 <52419336+IchHabeHunger54@users.noreply.github.com> Date: Sun, 22 Oct 2023 12:35:23 +0200 Subject: [PATCH 09/27] Update docs/blocks/index.md Co-authored-by: ChampionAsh5357 --- docs/blocks/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 9658dc10c..6f24c8d8c 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -14,7 +14,7 @@ Due to this, a block should only ever be instantiated once, and that is during r public static final RegistryObject MY_BLOCK = BLOCKS.register("my_block", () -> new Block(...)); ``` -After registering the block, all references to the new `my_block` should use this constant. For example, if you want to check if the block at a given position is a `my_block`, the code for that would look something like this: +After registering the block, all references to the new `my_block` should use this constant. For example, if you want to check if the block at a given position is `my_block`, the code for that would look something like this: ```java level.getBlockState(position).is(MyBlockRegistrationClass.MY_BLOCK.get()); From 93a5b31a11ab2e9ff47a4923446c45145ad03cdd Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 <52419336+IchHabeHunger54@users.noreply.github.com> Date: Sun, 22 Oct 2023 12:47:08 +0200 Subject: [PATCH 10/27] Update docs/blocks/index.md Co-authored-by: ChampionAsh5357 --- docs/blocks/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 6f24c8d8c..37b365180 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -57,7 +57,7 @@ A `BlockItem` must be registered separately from the block. This is because a bl ### More Functionality -Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a non-1x1x1 hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; these are documented in the [`Block` reference][blockreference]. See also the Using blocks section below for some of the most common use cases for blocks. +Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a different hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; these are documented in the [`Block` reference][blockreference]. See also the Using blocks section below for some of the most common use cases for blocks. If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity][blockentities] should be used. The rule of thumb here is that if you have a finite amount of states, use blockstates, and if you have an infinite or near-infinite amount of states, use a block entity. From fa5b3744dca4e4bbd9cb18c34cb4020a4ebf8226 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Sun, 22 Oct 2023 12:53:59 +0200 Subject: [PATCH 11/27] remove reference (for PRing to Parchment instead), apply feedback --- docs/blocks/index.md | 26 +++-- docs/blocks/reference.md | 220 --------------------------------------- docs/blocks/states.md | 19 +++- 3 files changed, 32 insertions(+), 233 deletions(-) delete mode 100644 docs/blocks/reference.md diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 6f24c8d8c..568ba4eaf 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -11,17 +11,21 @@ Before we get started, it is important to understand that there is only ever one Due to this, a block should only ever be instantiated once, and that is during registration. Once the block is registered, you can then use the registered reference as needed. Consider this example (see the [Registration][registration] page if you do not know what you are looking at): ```java +//BLOCKS is a DeferredRegister public static final RegistryObject MY_BLOCK = BLOCKS.register("my_block", () -> new Block(...)); ``` After registering the block, all references to the new `my_block` should use this constant. For example, if you want to check if the block at a given position is `my_block`, the code for that would look something like this: ```java +//level.getBlockState(position) returns the blockstate placed in the given level (world) at the given position level.getBlockState(position).is(MyBlockRegistrationClass.MY_BLOCK.get()); ``` +This approach also has the convenient side effect that `block1 == block2` works and should be used instead of Java's `equals` method. + :::danger -As soon as you create a `new Block()` outside registration, things can and will break! +Do not call `new Block()` outside registration! As soon as you do that, things can and will break! ::: Creating Blocks @@ -32,10 +36,15 @@ Creating Blocks For simple blocks which need no special functionality (think cobblestone, wooden planks, etc.), the `Block` class can be used directly. To do so, during registration, instantiate `Block` with a `BlockBehaviour.Properties` parameter. This `BlockBehaviour.Properties` parameter can be created using `BlockBehaviour.Properties#of`, and it can be customized by calling its methods. The most important methods for this are: - `destroyTime` - Determines the time the block needs to be destroyed. + - Stone has a destroy time of 1.5, dirt has 0.5, obsidian has 50, and bedrock has -1 (unbreakable). - `explosionResistance` - Determines the explosion resistance of the block. + - Stone has an explosion resistance of 6.0, dirt has 0.5, obsidian has 1200, and bedrock has 3600000. - `sound` - Sets the sound the block makes when it is punched, broken, or placed. + - The default value is `SoundType.STONE`. See the [Sounds page][sounds] for more details. - `lightLevel` - Sets the light emission of the block. Accepts a function with a `BlockState` parameter that returns a value between 0 and 15. + - For example, glowstone uses `state -> 15`, and torches use `state -> 14`. - `friction` - Sets the friction (slipperiness) of the block. + - Default value is 0.6. Ice uses 0.98. So for example, a simple implementation would look something like this: @@ -47,7 +56,7 @@ public static final RegistryObject MY_BETTER_BLOCK = BLOCKS.register("my_ .lightLevel(state -> 7))); ``` -For further documentation, see the [`BlockBehaviour.Properties` reference][propertiesreference]. For more examples, or to look at the values used by Minecraft, have a look at the `Blocks` class. +For further documentation, see the source code of `BlockBehaviour.Properties`. For more examples, or to look at the values used by Minecraft, have a look at the `Blocks` class. :::note It is important to understand that a block in the world is not the same thing as in an inventory. What looks like a block in an inventory is actually a `BlockItem`, a special type of [item] that places a block when used. This also means that things like the creative tab or the max stack size are handled by the corresponding `BlockItem`. @@ -76,7 +85,7 @@ In several situations, multiple methods of `Block` are used at different times. ### Placing a Block -Block placement logic is called from `BlockItem#useOn` (or some subclass's implementation thereof, such as in `PlaceOnWaterBlockItem`, which is used for lily pads). For more information on how the game gets there, see the [Interaction Pipeline][interactionpipeline]. +Block placement logic is called from `BlockItem#useOn` (or some subclass's implementation thereof, such as in `PlaceOnWaterBlockItem`, which is used for lily pads). For more information on how the game gets there, see the [Interaction Pipeline][interactionpipeline]. In practice, this means that as soon as a `BlockItem` is right-clicked (for example a cobblestone item), this behavior is called. - Several prerequisites are checked, for example that you are not in spectator mode, that all required feature flags for the block are enabled or that the block in question is not outside the world border. If at least one of these checks fails, the pipeline ends. - `Block#canBeReplaced` is called for the block currently at the position where the block is tried to place. If it returns `false`, the pipeline ends. @@ -131,12 +140,14 @@ The following subsections further break down these stages into actual method cal - `Item#onBlockStartBreak` is called. If it returns `true`, the pipeline moves to the "finishing" stage. - Server-only: `IForgeBlock#canHarvestBlock` is called. -- `Block#playerWillDestroy` is called. -- The blockstate is removed from the level via a `Level#setBlock` call with `Blocks.AIR.defaultBlockState()` as the blockstate parameter. - - In that `Level#setBlock` call, `Block#onRemove` is called. +- `Block#onDestroyedByPlayer` is called. If it returns `false`, the pipeline moves to the "finishing" stage. In that `Block#onDestroyedByPlayer` call: + - `Block#playerWillDestroy` is called. + - The blockstate is removed from the level via a `Level#setBlock` call with `Blocks.AIR.defaultBlockState()` as the blockstate parameter. + - In that `Level#setBlock` call, `Block#onRemove` is called. - `Block#destroy` is called. - Server-only: If the previous call to `IForgeBlock#canHarvestBlock` returned `true`, `Block#playerDestroy` is called. -- Server-only: `Block#popExperience` is called. +- Server-onlĂ˝: `IForgeBlock#getExpDrop` is called. +- Server-only: `Block#popExperience` is called with the result of the previous `IForgeBlock#getExpDrop` call, if that call returned a value greater than 0. #### The "Finishing" Stage @@ -162,7 +173,6 @@ Random ticking is used by a wide range of mechanics in Minecraft, such as plant [events]: ../concepts/events.md [interactionpipeline]: ../items/interactionpipeline.md [item]: ../items/index.md -[propertiesreference]: reference.md#blockbehaviourproperties [registration]: ../concepts/registries.md#methods-for-registering [resources]: ../resources/client/index.md [sounds]: ../gameeffects/sounds.md diff --git a/docs/blocks/reference.md b/docs/blocks/reference.md deleted file mode 100644 index 8b06d10cd..000000000 --- a/docs/blocks/reference.md +++ /dev/null @@ -1,220 +0,0 @@ -Method Reference -================ - -This article is a reference for all protected or public methods in various block-related classes. - -`Block` -------- - -:::note -Some of these methods are actually located in `BlockBehaviour`, the abstract superclass of `Block`, or in `IForgeBlock`, a NeoForge-added interface implemented by `Block` that adds extra utilities for modders to the `Block` class. However, for all our intents and purposes, we can treat them as if they were located in `Block` itself. -::: - -### Static methods - -| Method | Description | -|---------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `public static Block byItem(@Nullable Item)` | If the given item is a `BlockItem`, that `BlockItem`'s block is returned. Otherwise, `Blocks.AIR` is returned. | -| `public static VoxelShape box(double, double, double, double, double, double)` | Creates a `VoxelShape` with the given corner points. Parameter order is x1, y1, z1, x2, y2, z2. The unit used is single pixels, or in other words, 1 / 16 of a block. So for example, if you want a shape that is exactly one pixel tall, you'd use `box(0, 0, 0, 16, 1, 16);`. | -| `public static BlockState updateOrDestroy(BlockState, BlockState, LevelAccessor, BlockPos, int, int)` | Replaces the old blockstate (first parameter) with the new blockstate (second parameter) in the given level at the given position. The first `int` parameter is the update flags (see [Using Level#setBlock][setblock] for more information). The second `int` parameter is the amount of leftover worldgen recursions. It is recommended to use the overload that omits this parameter if you are not doing worldgen. | -| `public static BlockState updateOrDestroy(BlockState, BlockState, LevelAccessor, BlockPos, int)` | Overload of `updateOrDestroy(BlockState, BlockState, LevelAccessor, BlockPos, int, int)` that uses the default recursion amount of 512 as the second int parameter. | -| `public static BlockState pushEntitiesUp(BlockState, BlockState, LevelAccessor, BlockPos)` | Helper method that pushes entities out of the second `BlockState`'s bounds (if it is greater than the first `BlockState`'s bounds). Used in scenarios such as when farmland turns back into dirt and consequently has its shape increased back to a full block. | -| `public static BlockState updateFromNeighbourShapes(BlockState, LevelAccessor, BlockPos)` | With the provided `BlockState`, performs neighbor checks for all neighboring blocks in the given level at the given position. Used for example by Endermen when they place down a block they are holding. | -| `public static boolean isExceptionForConnection(BlockState)` | Whether the given state is an exception for connection by fences, walls and iron bars. If `true`, these blocks will not connect with the given state, even if they would connect otherwise. `true` for all types of Leaves, all types of Shulker Boxes, Barriers, Carved Pumpkins, Jack o'Lanterns, Melons and Pumpkins. | -| `public static boolean shouldRenderFace(BlockState, BlockGetter, BlockPos, Direction, BlockPos)` | Calculates whether the given blockstate's face in the given direction should be rendered or not. | -| `public static boolean canSupportRigidBlocks(BlockGetter, BlockPos)` | Whether the state at the given position in the given level can support a rigid block or not. Rigid blocks are blocks like rails or pressure plates that require only a solid top face to be placed, so using this method means that they can also be placed on non-full blocks that have a full solid top face, for example a top slab. | -| `public static boolean canSupportCenter(BlockGetter, BlockPos, Direction)` | Whether the state at the given position in the given level can support a center block in the given direction or not. Center blocks are blocks that require a solid center, but can be placed on blocks that do not have a full face in that direction. Prime examples would be a torch or a candle placed on a fence, or a lantern or a bell placed on the bottom face of a fence. | -| `public static int getId(@Nullable BlockState)` | Returns the numerical ID of a blockstate by performing a lookup in the blockstate registry. The parameter may be `null`, in which case 0 is returned. Used for networking. | -| `public static BlockState stateById(int)` | Counterpart of `getId`, returns the blockstate associated with the given integer by performing a lookup in the blockstate registry. If the given integer does not correspond to a blockstate, `Blocks.AIR.defaultBlockState()` is returned instead. Used for networking. | -| `public static boolean isFaceFull(VoxelShape, Direction)` | Whether the given shape is a full shape in the given direction or not. | -| `public static boolean isShapeFullBlock(VoxelShape)` | Whether the given shape is a full 1x1x1 block shape or not. | -| `public static List getDrops(BlockState, ServerLevel, BlockPos, @Nullable BlockEntity)` | Rolls the loot table for the given blockstate and returns the results as a `List`. Includes the position context, the block entity context if the block entity parameter is not `null`, and an empty tool context when rolling the loot table. | -| `public static List getDrops(BlockState, ServerLevel, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack)` | Alternative variant of `getDrops(BlockState, ServerLevel, BlockPos, @Nullable BlockEntity)` that additionally includes entity context if the entity is not `null`, and tool context using the given `ItemStack` when rolling the loot table. | -| `public static void dropResources(BlockState, Level, BlockPos, @Nullable BlockEntity)` | Generates drops by calling `getDrops(BlockState, ServerLevel, BlockPos, @Nullable BlockEntity)` and drops them in the level as item entities. Also calls `BlockState#spawnAfterBreak(ServerLevel, BlockPos, ItemStack, boolean)` with `ItemStack.EMPTY` and `true` for the last two parameters. | -| `public static void dropResources(BlockState, Level, BlockPos)` | Alternative variant of `dropResources(BlockState, Level, BlockPos)` that omits the block entity parameter. Equivalent to calling `dropResources(BlockState, Level, BlockPos, null)` with the same first three parameters. | -| `public static void dropResources(BlockState, Level, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack, boolean)` | Generates drops by calling `getDrops(BlockState, ServerLevel, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack)` and drops them in the level as item entities. Also calls `BlockState#spawnAfterBreak(ServerLevel, BlockPos, ItemStack, boolean)` with the corresponding parameters of this method. | -| `public static void dropResources(BlockState, Level, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack)` | Alternative variant of `dropResources(BlockState, Level, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack, boolean)` that omits the boolean parameter. Equivalent to calling `dropResources(BlockState, Level, BlockPos, @Nullable BlockEntity, @Nullable Entity, ItemStack, true)` with the same first six parameters. | -| `public static void popResource(Level, BlockPos, ItemStack)` | Drops the given `ItemStack` into the given level at the given position, respecting the `doTileDrops` gamerule. | -| `public static void popResource(Level, BlockPos, Direction, ItemStack)` | Drops the given `ItemStack` into the given level at the given position, "popping off" the given direction and respecting the `doTileDrops` gamerule. | - -### Instance methods - -:::note -For methods with a `BlockState` parameter, it can be generally assumed that the given blockstate is a state of this block (unless stated otherwise). -::: - -| Method | Description | -|---------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `protected void createBlockStateDefinition(StateDefinition.Builder)` | Defines the block state properties this block has. See [Implementing Blockstates][implementingblockstates] for more information. | -| `public StateDefinition getStateDefinition()` | Returns the blockstate definition. Used in a variety of internal places, such as the blockstate parser for commands. | -| `protected final void registerDefaultState(BlockState)` | Registers the default blockstate for this block. Should be called from the block constructor. | -| `public final BlockState defaultBlockState()` | Returns the default blockstate for this block. | -| `public final BlockState withPropertiesOf(BlockState)` | Copies the properties from the given blockstate to this block's default blockstate. This can be a blockstate belonging to a different block, in which case only the properties present on both will be copied. For example, this can be used to copy the rotation and slope properties of a regular rail to a powered rail. | -| `public FluidState getFluidState(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getFluidState` instead.** Returns the fluid state of this block. Returns `Fluids.EMPTY.defaultFluidState()` by default. Waterloggable blocks override this to return `Fluids.WATER.defaultFluidState()` if their `waterlogged` property is set to `true`. | -| `public Item asItem()` | Returns the `BlockItem` associated with the block, or `null` if no item is associated. | -| `protected Block asBlock()` | Helper for the abstract `BlockBehaviour` superclass to cast itself to `Block` where needed. | -| `public ItemStack getCloneItemStack(Level, BlockPos, BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Called when the player uses Pick Block (middle mouse button) in creative mode. Typically returns an `ItemStack` containing this block's associated `BlockItem`. Overridden by some blocks; for example, flower pots return the containing plant item here if available. | -| `public String toString()` | Returns the string representation of this block. Format is `"Block{namespace:path}"`, so for example for the block `"minecraft:cobblestone"`, this would be `"Block{minecraft:cobblestone}".` | -| `public String getDescriptionId()` | Returns this block's description ID, a.k.a. translation key. Has the format `"block.."`. For example, for the block `"minecraft:cobblestone"`, this returns `"block.minecraft.cobblestone"`. | -| `public MutableComponent getName()` | Returns a component containing this block's display name, using the translation key. | -| `protected boolean isAir(BlockState)` | Returns whether the given blockstate is air or not, set in `BlockBehaviour.Properties`. | -| `public MapColor defaultMapColor()` | Returns the `MapColor` of the default block state. | -| `public float defaultDestroyTime()` | Returns the destroy speed of the default block state. | -| `public float getExplosionResistance()` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns this block's explosion resistance, as set for this block in `BlockBehaviour.Properties`. | -| `public SoundType getSoundType(BlockState)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Returns the sound type set in `BlockBehaviour.Properties`. | -| `public float getFriction()` | Returns the friction value set in `BlockBehaviour.Properties`. | -| `public float getSpeedFactor()` | Returns the speed factor set in `BlockBehaviour.Properties`. | -| `public float getJumpFactor()` | Returns the jump factor set in `BlockBehaviour.Properties`. | -| `public float getMaxHorizontalOffset()` | Returns the max horizontal offset for blocks with random offset. Default value is 0.25, Pointed Dripstone overrides this to 0.125. See `BlockBehaviour.Properties#offsetType` for more information. | -| `public float getMaxVerticalOffset()` | Returns the max vertical offset for blocks with random offset. Default value is 0.2, Small Dripleaf overrides this to 0.1. See `BlockBehaviour.Properties#offsetType` for more information. | -| `public FeatureFlagSet requiredFeatures()` | Returns the required features set in `BlockBehaviour.Properties`. | -| `public boolean hasDynamicShape()` | Returns whether the block has a dynamic shape or not, as set in `BlockBehaviour.Properties`. | -| `public boolean isRandomlyTicking(BlockState)` | Returns whether the block can be randomly ticked or not, as set in `BlockBehaviour.Properties`. | -| `public final ResourceLocation getLootTable()` | Returns the loot table of the block, set in `BlockBehaviour.Properties`. | -| `public void tick(BlockState, ServerLevel, BlockPos, RandomSource)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#tick` instead.** Performs a server tick on the blockstate. Does nothing by default. See [block ticking][blocktick] for more information. | -| `public void randomTick(BlockState, ServerLevel, BlockPos, RandomSource)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#randomTick` instead.** Performs a random tick on the blockstate. The default implementation calls `Block#tick(BlockState, ServerLevel, BlockPos, RandomSource)`. See [block ticking][blocktick] for more information. | -| `public void animateTick(BlockState, Level, BlockPos, RandomSource)` | Performs a client tick on the blockstate. Does nothing by default. See [block ticking][blocktick] for more information. | -| `public void handlePrecipitation(BlockState, Level, BlockPos, Biome.Precipitation)` | Performs a weather tick on the blockstate. Does nothing by default. See [block ticking][blocktick] for more information. | -| `public BlockState canBeReplaced(BlockState, BlockPlaceContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canBeReplaced` instead.** Returns whether the state can be replaced by another block. Returns `false` if the `replaceable` field in `BlockBehaviour.Properties` is `false` or if the blockstate being placed is the same as the given blockstate (since you obviously cannot replace grass with grass), and `true` if neither of those apply. Overridden by some blocks, mainly decorative blocks, for various additions to that rule. See the [block placement pipeline][blockplace] for more information. | -| `public BlockState canBeReplaced(BlockState, Fluid)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canBeReplaced` instead.** Variant of `#canBeReplaced(BlockState, BlockPlaceContext)` that is called when a block would be replaced by a fluid. Returns `false` if the `replaceable` field in `BlockBehaviour.Properties` is `false` or if the given blockstate is not solid, and `true` otherwise. Overridden by end portals and end gateways to always return `false`. See the [block placement pipeline][blockplace] for more information. | -| `public BlockState getStateForPlacement(BlockPlaceContext)` | Called when trying to place a `BlockItem` of this block down. The given `BlockPlaceContext` contains information such as the level, the position, the player, the stack and many more that can be used to determine the result. Returns the default block state, but is overridden in a wide range of places. For example, fences use this method to connect to other blocks when placing. See the [block placement pipeline][blockplace] for more information. | -| `public void onPlace(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onPlace` instead.** Called when the blockstate is placed. Parameter order is `state, level, position, oldStateAtThatPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Overridden in several places, mostly for performing post-placement behavior. See the [block placement pipeline][blockplace] for more information. | -| `public void setPlacedBy(Level, BlockPos, BlockState, @Nullable LivingEntity, ItemStack)` | Called **after** the blockstate has been placed down by the given `LivingEntity`. Overridden for example by player heads to fetch the associated player skin. See the [block placement pipeline][blockplace] for more information. | -| `public boolean canSurvive(BlockState, LevelReader, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#canSurvive` instead.** Returns whether the blockstate can survive here or not. Returns `true` by default. Overridden by various blocks that have placement requirements, for example plants that need to check if they are placed on the correct soil, or hanging lanterns that check if they are actually still hanging. See the [block placement pipeline][blockplace] for more information. | -| `public BlockState rotate(BlockState, Rotation)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#rotate` instead.** Returns the state to use after rotating the block with the given rotation. Returns the given state by default. Overridden by all blocks with a `facing` property to consider said `facing` property. | -| `public BlockState mirror(BlockState, Mirror)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#mirror` instead.** Returns the state to use after mirroring the block with the given mirror. Returns the given state by default. Overridden by all blocks with a `facing` property to consider said `facing` property. | -| `public InteractionResult use(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#use` instead.** Called as part of the [Interaction Pipeline][interactionpipeline] when a block is activated or used. For example, this is where pressing a button or opening a crafting table GUI happens. For details on when exactly this is called and what to use as the return value, please refer to the [explanation of `Block#use` in the Interaction Pipeline article][blockuse]. | -| `public boolean triggerEvent(BlockState, Level, BlockPos, int, int)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#triggerEvent` instead.** Called on the server when `Level#blockEvent` is called. Called on the client as well if it returned `true` on the server. The primary use of this mechanic is to notify the other side of changes that cannot be sent via a block entity. Currently, this is only used by comparators. | -| `public MenuProvider getMenuProvider(BlockState, Level, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getMenuProvider` instead.** Returns a menu provider to show when right-clicking the block. Returns `null` by default. Overridden by blocks that don't have a `BlockEntity` but still have a GUI, such as the Crafting Table, the Smithing Table or the Grindstone. | -| `public void attack(BlockState, ServerLevel, BlockPos, Player)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#attack` instead.** Called when a player begins breaking the block. For example, note blocks play their note here, and the dragon egg teleports away. The default implementation is empty. See the [block breaking pipeline][blockbreak] for more information. | -| `public void playerWillDestroy(Level, BlockPos, BlockState, Player)` | Called immediately **before** the blockstate will be destroyed by the given player. Called regardless of whether the player is using the correct tool. By default, this spawns breaking particles and angers piglins if applicable. Overridden in various places for additional behavior, for example by doors to break their upper/lower part as well. See the [block breaking pipeline][blockbreak] for more information. | -| `protected void spawnDestroyParticles(Level, Player, BlockPos, BlockState)` | Called by `Block#playerWillDestroy`. Sends a packet to the client to spawn breaking particles there. Overridden to no-op by fire blocks. | -| `public void onRemove(BlockState, Level, BlockPos, BlockState, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onRemove` instead.** Called during blockstate removal. Parameter order is `state, level, position, newStateAtThatPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Default behavior removes a block entity present at the position from the level, if applicable. Overridden in several places, mostly to either spill out container content or to perform a final redstone update. See the [block breaking pipeline][blockbreak] for more information. | -| `public void destroy(LevelAcccessor, BlockPos, BlockState)` | Called immediately **after** the blockstate has been destroyed by the player. Used by pistons to destroy the piston head as well if they are activated. See the [block breaking pipeline][blockbreak] for more information. | -| `public void playerDestroy(Level, Player, BlockPos, BlockState, @Nullable BlockEntity, ItemStack)` | Called **after** the given player has destroyed the given blockstate with the given tool at the given position in the given level. Called only on the server side, and only if the block has used a sufficient tool for drops to spawn, so for example, this will not be called when breaking diamond ore with a wooden pickaxe. Default behaviour handles resource dropping. Overridden for example by beehives that spawn bees in this method when destroyed. See the [block breaking pipeline][blockbreak] for more information. | -| `public void popExperience(ServerLevel, BlockPos, int)` | Drops the given amount of experience in the given level at the given position. Called only on the server side. Respects the `doTileDrops` gamerule. See the [block breaking pipeline][blockbreak] for more information. | -| `protected void tryDropExperience(ServerLevel, BlockPos, ItemStack, IntProvider)` | Helper method for dropping experience if the given `ItemStack` is not enchanted with Silk Touch. Currently unused. | -| `public List getDrops(BlockState, LootParams.Builder)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getDrops` instead.** Called by the static `Block.getDrops` methods. Rolls the loot table for the block with blockstate context. Overridden by some blocks that add custom modifications to the results, such as shulker boxes that add their inventory to the dropped `ItemStack`. | -| `public void spawnAfterBreak(BlockState, ServerLevel, BlockPos, ItemStack, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#spawnAfterBreak` instead.** Spawns entities after breaking this blockstate. The `boolean` parameter determines whether to drop experience or not. The default implementation drops experience if the `boolean` parameter is `true` and `Block#getExpDrop` returns more than 0. Overridden by ore blocks and spawners to drop xp, and by infested blocks to spawn silverfish. | -| `public void dropFromExplosion(Explosion)` | **DEPRECATED: Use the `IForgeBlock` variant instead!** Whether this block should drop when destroyed by an explosion. `true` by default, overridden to return `false` for TNT. | -| `public void wasExploded(Level, BlockPos, Explosion)` | Called **after** the blockstate has been destroyed by an explosion. | -| `public void stepOn(Level, BlockPos, BlockState, Entity)` | Called when an entity stands on this blockstate. Used for example by magma blocks to apply magma damage. | -| `public void entityInside(BlockState, ServerLevel, BlockPos, Entity)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#entityInside` instead.** Called when the given entity is inside this blockstate. Does nothing by default. For example, fire blocks ignite entities that stand in them here. | -| `public void fallOn(Level, BlockState, BlockPos, Entity, float)` | Called when an entity falls onto this blockstate from the given distance. Default behavior is to cause fall damage. Overridden by various blocks that modify fall damage, for example beds or pointed dripstone. | -| `public void updateEntityAfterFallOn(Level, Entity)` | Called **after** an entity falls onto this block and `#fallOn` has already been called. This method is mainly responsible for handling the given entity's movement after falling on the block. Default behavior is to cancel any vertical movement. Overridden by beds and slime blocks to perform their bouncing behavior. | -| `public void onProjectileHit(Level, BlockState, BlockHitResult, Projectile)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#onProjectileHit` instead.** Called when a `Projectile` (for example an arrow or a fireball) hits the blockstate. Does nothing by default. For example, TNT ignites itself here when hit with a burning projectile. | -| `public boolean propagatesSkylightDown(BlockState, BlockGetter, BlockPos)` | Whether this block propagates skylight through itself or not. By default, this returns `true` if the block is not a full block and has no fluid state. However, this is overridden by several blocks, such as glass which always lets light pass through it. | -| `public boolean skipRendering(BlockState, BlockState, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#skipRendering` instead.** Whether this block's rendering should be skipped or not, given the context of the adjacent blockstate (second `BlockState` parameter). Used for example by glass to not render itself over and over in a glass layer that's several blocks wide. | -| `public RenderShape getRenderShape(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getRenderShape` instead.** Defines how the block should be rendered. Possible values are `RenderShape.ENTITYBLOCK_ANIMATED` for blocks that use a [`BlockEntityRenderer`][ber], `RenderShape.MODEL` if a JSON model or a mix of JSON model and `BlockEntityRenderer` is used, and `RenderShape.INVISIBLE` to not render at all. The default value is `RenderShape.MODEL`. | -| `public VoxelShape getShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getShape` instead.** Returns the block's selection shape. Returns a 1x1x1 block shape by default. Overridden by blocks that have a non-1x1x1 shape, for example slabs, stairs, walls, fences, carpets, beds and many many others. | -| `public VoxelShape getBlockSupportShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getBlockSupportShape` instead.** Returns the shape to use when checking if this block can support another block. Returns the collision shape by default. Overridden by some blocks with unusual collision shapes, for example soul sand or mud, to still support blocks on top of them. | -| `public VoxelShape getInteractionShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getInteractionShape` instead.** Returns the shape to use for special interactions with this block. Returns an empty shape by default. Overridden by blocks that have different interactions depending on the side used, for example hoppers or cauldrons. | -| `public VoxelShape getVisualShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getVisualShape` instead.** Returns what is considered the block's visual shape. Returns the collision shape by default. Overridden by some blocks that consider the visual shape to be the selection shape, such as fences and iron bars. | -| `public VoxelShape getCollisionShape(BlockState, BlockGetter, BlockPos, CollisionContext)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getCollisionShape` instead.** Returns the block's collision shape, a.k.a. hitbox. Returns the selection shape if collision is enabled (as set in the `BlockBehaviour.Properties`) and an empty shape if not. Overridden by blocks where the selection shape is different from the collision shape, such as walls, fence gates, lecterns or soul sand. | -| `public VoxelShape getOcclusionShape(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getOcclusionShape` instead.** Returns the shape to use for occlusion by the light engine. Returns the normal shape by default. Overridden by some blocks, for example fences or lecterns, to return a smaller shape. | -| `public boolean isCollisionShapeFullBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isCollisionShapeFullBlock` instead.** Returns `true` if the block's collision shape is a full block, `false` if not. | -| `public boolean isOcclusionShapeFullBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isOcclusionShapeFullBlock` instead.** Returns `true` if the block's occlusion shape is a full block, `false` if not. | -| `public boolean useShapeForLightOcclusion(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#useShapeForLightOcclusion` instead.** Whether the block should use its shape for light occlusion or not. Returns `false` by default, but is overridden to `true` by many blocks that don't have a full block shape, such as slabs, stairs or sculk sensors. | -| `public int getLightBlock(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getLightBlock` instead.** Returns how much the block blocks light. Returns 15 for solid blocks, 0 if `Block#propagatesSkylightDown(Level, BlockPos)` returns `true`, and 1 otherwise. Overridden to be 15 by Tinted Glass, despite being a non-solid block. | -| `public float getShadeBrightness(BlockState, BlockGetter, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getShadeBrightness` instead.** Returns the shade brightness of this block, used by the light engine. Returns 0.2 for solid blocks and 1.0 for all other blocks by default. Overridden by some blocks with unusual collision shapes, for example soul sand or mud, to still act like a solid block in this situation. | -| `public boolean updateShape(BlockState, Direction, BlockState, LevelAccessor, BlockPos, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#updateShape` instead.** Updates the blockstate given the neighbor context. Parameter order is `ownState, neighborDirection, neighborState, level, ownPosition, neighborPosition`. Returns itself by default, overridden in a lot of places, for example by fences, walls or blocks that are attached to another block. | -| `public void updateIndirectNeighbourShapes(BlockState, BlockGetter, BlockPos, int, int)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#updateIndirectNeighbourShapes` instead.** Updates the diagonal neighbor blockstates. The `int` parameters are the flags and worldgen recursion values, see `Block.updateOrDestroy` for a more detailed explanation of those. Does nothing by default, but is overridden by redstone wires. | -| `public boolean neighborChanged(BlockState, Level, BlockPos, Block, BlockPos, boolean)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#neighborChanged` instead.** Called when a neighboring block has been changed. Parameter order is `state, level, fromPosition, movedBlock, toPosition, movedByPiston`. The `movedByPiston` parameter denotes if the change was caused by a piston moving the neighbor block or not. Overridden in several places, mostly with some relation to redstone. | -| `protected ImmutableMap getShapeForEachState(Function)` | Used by the internal shape cache for blockstate-specific shapes. Overridden by big dripleaves to handle the "falling through" when tilting. | -| `public long getSeed(BlockState, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getSeed` instead.** Returns a seed to use when randomly selecting one of multiple possible models. | -| `public boolean hasAnalogOutputSignal(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#hasAnalogOutputSignal` instead.** Whether this block has a redstone output signal that comparators can listen to. This is not saying that the block always emits a redstone signal. To get the actually emitted redstone signal, use `Block#getAnalogOutputSignal`. | -| `public int getAnalogOutputSignal(BlockState, Level, BlockPos)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getAnalogOutputSignal` instead.** Returns the analog redstone value emitted by this block, which can be read by comparators. Returns 0 by default. Overridden by various containers and redstone components to return their redstone signal value, for example a value from 0 to 15 by hoppers. This does not return the redstone power value of the block itself, see `Block#getSignal` for that. | -| `public int getSignal(BlockState, ServerLevel, BlockPos, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getSignal` instead.** Returns the **outgoing** redstone signal strength of the block in the given direction. Returns 0 by default. For example, this would return 15 for an activated lever and 0 for a deactivated lever. | -| `public int getDirectSignal(BlockState, ServerLevel, BlockPos, Direction)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#getDirectSignal` instead.** Returns the **incoming** redstone signal strength of the block from the given direction. Returns 0 by default. Overridden by blocks that only accept redstone power if it comes from the correct side, such as redstone torches. | -| `public boolean isSignalSource(BlockState)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isSignalSource` instead.** Whether the block is a signal source. Note that vanilla doesn't actually use this a lot, only checking it in redstone wires and rails and overriding it to unconditionally return `true` in a lot of places where it does not actually make sense. This is because most of the time, vanilla simply checks the `powered` blockstate property instead. | -| `public boolean isPathfindable(BlockState, BlockGetter, BlockPos, PathComputationType)` | **CALL DEPRECATION: Overriding is fine, calls should use `BlockState#isPathfindable` instead.** Whether mobs can pathfind over the blockstate or not. Default behavior checks for a full block, or for water if the PathComputationType is `WATER`. Overridden to `false` in a variety of places, for example soul sand, respawn anchors or various non-full blocks, just to be sure. | -| `public boolean isPossibleToRespawnInThis(BlockState)` | Whether respawning in this blockstate is possible or not. Default behaviour is to return `true` if the blockstate is not solid and not a liquid. Overridden by banners, pressure plates and signs to return `true` despite being solid. | -| `public void appendHoverText(ItemStack, @Nullable BlockGetter, List, TooltipFlag)` | Called by the method of the same name in `Item`, this method is responsible for appending hover texts (tooltips) to the item. Does nothing by default. Overridden for example by shulker boxes that add their content tooltips here. | -| `public Holder.Reference builtInRegistryHolder()` | **DEPRECATED.** Internal reference to the builtin block registry holder. **Do not use this, use one of the safer equivalents in `ForgeRegistries.BLOCKS` instead, for example `#getDelegateOrThrow`.** | -| `public Object getRenderPropertiesInternal()` | **DEPRECATED FOR REMOVAL: There is no need for you to use this!** If you are using this somewhere in legacy code, ask in the Discord on how to replace this. NeoForge-added. | -| `public void initializeClient(Consumer consumer)` | Allows for adding custom client-side behavior in the form of a class implementing `IClientBlockExtensions`. NeoForge-added. | -| `public boolean canSustainPlant(BlockState, BlockGetter, BlockPos, Direction, IPlantable)` | Whether this blockstate can sustain the given plant, in the form of an `IPlantable`. Note that this system has found to be flawed and will likely be replaced with a better system in the future. NeoForge-added. | - -`BlockState` ------------- - -:::note -Some of these methods are actually located in `BlockBehaviour.BlockStateBase`, the abstract superclass of `BlockState`, or in `IForgeBlockState`, a NeoForge-added interface implemented by `Block` that adds extra utilities for modders to the `BlockState` class. However, for all our intents and purposes, we can treat them as if they were located in `BlockState` itself. -::: - -| Method | Description | -|--------|----------------------| -| `test` | This is a test entry | -| `todo` | More work is needed | - -`BlockBehaviour.Properties` ---------------------------- - -### Static methods - -| Method | Description | -|-------------------------------------------------|---------------------------------------------------------------------------------------| -| `public static Properties of()` | Returns a new `Properties` object with default values. | -| `public static Properties copy(BlockBehaviour)` | Returns a new `Properties` object with the values used by the given `BlockBehaviour`. | - -### Instance methods - -All instance methods of `Properties` are `public` and return themselves (`return this;`). As a result, all the below methods can be chained at will; that is, appended in whatever order you like. An example from the `Blocks` class best shows this: -```java -public static final Block OAK_PLANKS = register("oak_planks", new Block(BlockBehaviour.Properties.of() - .mapColor(MapColor.WOOD) - .instrument(NoteBlockInstrument.BASS) - .strength(2.0F, 3.0F) - .sound(SoundType.WOOD) - .ignitedByLava() -)); -``` - -| Method | Description | -|-------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `air()` | Tells the game to consider the block as air. | -| `destroyTime(float)` | Sets the block's destroy time. Default value is 0. Typical values include 1.5 for stone, 0.5 for dirt, 50 for obsidian, and -1 for unbreakable blocks such as bedrock. | -| `explosionResistance(float)` | Sets the block's explosion resistance. Default value is 0. Typical values include 6 for stone, 0.5 for dirt, 1200 for obsidian, and 3600000 for unbreakable blocks such as bedrock. | -| `strength(float, float)` | Sets the block's destroy time (first parameter) and explosion resistance (second parameter). Equivalent to calling `.destroyTime(float).explosionResistance(float)` with the same parameters. | -| `strength(float)` | Sets the block's destroy time and explosion resistance. Equivalent to calling `.destroyTime(float).explosionResistance(float)` with the same parameter. | -| `instabreak()` | Sets the block's destroy time and explosion resistance to 0. Equivalent to calling `.destroyTime(0).explosionResistance(0)`. | -| `requiresCorrectToolForDrops()` | Sets the block to require the correct tool in order to drop anything. If false, the correct tool will mine faster, but items will drop regardless of what tool was used. `true` for blocks like stone or the various ores, `false` for blocks like planks or dirt. | -| `noLootTable()` | Sets the block to not use a loot table, causing the block to not drop anything. Note that no drops can also be achieved by using an empty loot table instead of no loot table at all, so only use this where applicable. Vanilla uses include unobtainable blocks (bedrock, barriers, etc.) and fluids (water/lava blocks). | -| `dropsLike(Block)` | **DEPRECATED: Use `lootFrom` instead!** Sets the block to use the given block's loot table instead of its own. | -| `lootFrom(Supplier)` | Sets the block to use the given block's loot table instead of its own. Uses a `Supplier` to allow directly passing in `RegistryObject`s. | -| `noParticlesOnBreak()` | Disables breaking particles for the block. | -| `replaceable()` | Enables the block to be replaceable by other blocks. This is relevant when trying to place a block into another blocks. For example, grass is replaceable, while flowers are not. | -| `friction(float)` | Sets the block's friction (slipperiness) value. Default friction value is 0.6, Ice, Packed Ice and Frosted Ice use 0.98, Blue Ice uses 0.989, and Slime Blocks use 0.8. | -| `speedFactor(float)` | Sets the block's speed factor. Entities that walk over the block will be slowed (if < 1) or sped up (if > 1) by this value. Default speed factor is 1, Soul Sand and Honey Blocks use 0.4. | -| `jumpFactor(float)` | Sets the block's jump factor. Entities that jump while standing on this block will have their jump height multiplied with this value. Default jump factor is 1, Honey Blocks use 0.5. | -| `sound(SoundType)` | Sets the block's sound type. The sound type is used when placing, mining or breaking a block. For information on how to get a `SoundType`, please refer to the [Sounds][sounds] section. | -| `lightLevel(ToIntFunction)` | Sets the block's light level, depending on the blockstate. This is a function to account for blocks like redstone lamps that have a `lit` property. The function must always return a value between 0 and 15 (both inclusive). | -| `mapColor(MapColor)` | Sets the block's map color to the given map color. | -| `mapColor(DyeColor)` | Overload of `mapColor` that accepts a `DyeColor`. The `DyeColor` is converted to its corresponding `MapColor` internally. | -| `mapColor(Function)` | Overload of `mapColor` that allows for blockstate-specific `MapColor`s. Used for example by beds, where the head part always uses `MapColor.WOOL`, while the foot part uses the bed's color. | -| `instrument(NoteBlockInstrument)` | Sets the block's note block instrument. The instrument is used for a note block placed above the block. A list of valid options can be found in the source code for `NoteBlockInstrument`. | -| `pushReaction(PushReaction)` | Sets the block's push reaction. Valid values for entities are `NORMAL` (push and pull), `DESTROY` (destroy when trying to push), `BLOCK` (block against pushing, cannot be pulled; used by hard blocks such as obsidian, as well as blocks that have an inventory), `IGNORE` (used for entites that can't be pushed/pulled, not to be used for blocks) and `PUSH_ONLY` (push, but not pull; used by Glazed Terracotta) | -| `ignitedByLava()` | Enables the block to be ignited when next to lava. Primarily used for wooden blocks. | -| `randomTicks()` | Enables random ticking for the block. Every tick, a set amount of blocks are selected in each chunk to be randomly ticked. The amount is determined by the `randomTickSpeed` gamerule (default is 3). If a block is selected and random ticking is enabled, then `Block#randomTick` is called for that block. | -| `noOcclusion()` | Disables occlusion for the block. | -| `noCollission()` | Disables collision **and occlusion** for the block. | -| `dynamicShape()` | Tells the game that the block has a dynamic shape. Used by vanilla in a few cases, such as piston heads or shulker boxes. | -| `forceSolidOn()` | ??? | -| `forceSolidOff()` | ??? | -| `isValidSpawn(StateArgumentPredicate>)` | Sets the block to be a valid spawn for entities that fulfill the given state predicate. | -| `isRedstoneConductor(StatePredicate)` | Sets the block to be a redstone conductor if the given state predicate is fulfilled. | -| `isSuffocating(StatePredicate)` | Sets the block to suffocate entities inside it if the given state predicate is fulfilled. | -| `isViewBlocking(StatePredicate)` | Sets the block to block the view for entities inside it if the given state predicate is fulfilled. Typically used with a predicate that is always `false`, for example by Glass. | -| `hasPostProcess(StatePredicate)` | Sets the block to have worldgen post processing if the given state predicate is fulfilled. Always true for Brown Mushrooms, Red Mushrooms and Magma Blocks. | -| `emissiveRendering(StatePredicate)` | Sets the block to have emissive rendering if the given state predicate is fulfilled. True for Magma Blocks and activated Sculk Sensors. | -| `offsetType(OffsetType)` | Sets the block's random position offset type. The random position offset slightly offsets a block's hitbox and model position to make it feel more natural. Has three possible values: `NONE` (default), `XZ` (horizontal) and `XYZ` (all directions). Grass and Ferns use `XYZ`, while many flowers and flower-like blocks use `XZ`. | -| `requiredFeatures(FeatureFlag...)` | Sets the block's required feature flags. The block will only be actually registered if all the passed feature flags are activated. Currently unused, but historically used for bamboo and cherry wood (among others) when they were in their experimental phase. | - -[ber]: ../blockentities/ber.md -[blockbreak]: index.md#breaking-a-block -[blockplace]: index.md#breaking-a-block -[blockuse]: ../items/interactionpipeline.md#blockuse -[implementingblockstates]: states.md#implementing-blockstates -[interactionpipeline]: ../items/interactionpipeline.md -[setblock]: states.md#levelsetblock -[sounds]: ../gameeffects/sounds.md diff --git a/docs/blocks/states.md b/docs/blocks/states.md index 303683a64..fad159e69 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -76,6 +76,7 @@ To further illustrate this, this is what the relevant bits of the `LeverBlock` c ```java public class LeverBlock extends Block { + // Note: It is possible to directly use the values in BlockStateProperties instead of referencing them here again. However, for the sake of simplicity and readability, it is recommended to add constants like this. public static final DirectionProperty FACING = BlockStateProperties.FACING; public static final BooleanProperty POWERED = BlockStateProperties.POWERED; @@ -89,7 +90,7 @@ public class LeverBlock extends Block { @Override protected void createBlockStateDefinition(StateDefinition.Builder pBuilder) { - pBuilder.add(FACING, POWERED); + pBuilder.add(FACING, POWERED); // this is where the properties are actually added to the state } @Override @@ -103,11 +104,19 @@ public class LeverBlock extends Block { Using Blockstates ----------------- -To go from `Block` to `BlockState`, call `Block#defaultBlockState()`. +To go from `Block` to `BlockState`, call `Block#defaultBlockState()`. The default blockstate can be changed through `Block#registerDefaultState`, as described above. -You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. Reusing our lever example, this would look something like `Direction direction = leverBlockState.getValue(LeverBlock.FACING);` +You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. Reusing our lever example, this would look something like this: -If you want to get a `BlockState` with a different set of values, simply call `BlockState#setValue(Property, T)` on an existing block state with the property and its value. With our lever, this goes something like `leverBlockState = leverBlockState.setValue(LeverBlock.FACING, Direction.SOUTH);` +```java +Direction direction = leverBlockState.getValue(LeverBlock.FACING); +``` + +If you want to get a `BlockState` with a different set of values, simply call `BlockState#setValue(Property, T)` on an existing block state with the property and its value. With our lever, this goes something like this: + +```java +leverBlockState = leverBlockState.setValue(LeverBlock.FACING, Direction.SOUTH); +``` :::note `BlockState`s are immutable. This means that when you call `#setValue(Property, T)`, you are not actually modifying the blockstate. Instead, a lookup is performed internally, and you are given the blockstate object you requested, which is the one and only object that exists with these exact property values. This also means that just calling `state#setValue` without saving it into a variable (for example back into `state`) does nothing. @@ -121,7 +130,7 @@ To set a `BlockState` in the level, use `Level#setBlock(BlockPos, BlockState, in The `int` parameter deserves some extra explanation, as its meaning is not immediately obvious. It denotes what is known as update flags. -To help setting the update flags correctly, there are a number of `int` constants in `Block`, prefixed with `UPDATE_`. Examples include `Block.UPDATE_NEIGHBORS` or `Block.UPDATE_CLIENTS`. These constants can be added together (for example `Block.UPDATE_NEIGHBORS + Block.UPDATE_CLIENTS`) if you wish to combine them. If you're unsure which one to use, use `Block.UPDATE_ALL`. +To help setting the update flags correctly, there are a number of `int` constants in `Block`, prefixed with `UPDATE_`. Examples include `Block.UPDATE_NEIGHBORS` or `Block.UPDATE_CLIENTS`. These constants can be bitwise-ORed together (for example `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`) if you wish to combine them. If you're unsure which one to use, use `Block.UPDATE_ALL`. [block]: index.md [blockentity]: ../blockentities/index.md From 1fbcd0407119d8f87a4140b7bf9cf92941f6b338 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Sun, 22 Oct 2023 13:06:28 +0200 Subject: [PATCH 12/27] remove faulty link to now-gone reference.md --- docs/blocks/index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 151c47d69..b295e96cb 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -66,7 +66,7 @@ A `BlockItem` must be registered separately from the block. This is because a bl ### More Functionality -Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a different hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; these are documented in the [`Block` reference][blockreference]. See also the Using blocks section below for some of the most common use cases for blocks. +Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a different hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; see the classes `Block`, `BlockBehaviour` and `IForgeBlock` for more information. See also the Using blocks section below for some of the most common use cases for blocks. If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity][blockentities] should be used. The rule of thumb here is that if you have a finite amount of states, use blockstates, and if you have an infinite or near-infinite amount of states, use a block entity. @@ -168,7 +168,6 @@ Random ticks occur every tick for a set amount of blocks in a chunk. That set am Random ticking is used by a wide range of mechanics in Minecraft, such as plant growth, ice and snow melting, or copper oxidizing. [blockentities]: ../blockentities/index.md -[blockreference]: reference.md#block [blockstates]: states.md [events]: ../concepts/events.md [interactionpipeline]: ../items/interactionpipeline.md From 32a3e051bca35019e02b2f122655f9dbbd556c9d Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Tue, 24 Oct 2023 15:56:12 +0200 Subject: [PATCH 13/27] implement feedback --- docs/blocks/index.md | 10 +++++++--- docs/blocks/states.md | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index b295e96cb..0a3c6d832 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -25,7 +25,11 @@ level.getBlockState(position).is(MyBlockRegistrationClass.MY_BLOCK.get()); This approach also has the convenient side effect that `block1 == block2` works and should be used instead of Java's `equals` method. :::danger -Do not call `new Block()` outside registration! As soon as you do that, things can and will break! +Do not call `new Block()` outside registration! As soon as you do that, things can and will break: + +- Blocks must be created while registries are unfrozen. NeoForge unfreezes registries for you and freezes them later, so registration is your time window to create blocks. +- If you try to create and/or register a block when registries are frozen again, the game will crash. On top of that, error messages are usually cryptic here, so it's best to avoid them. +- If you still manage to have a dangling block instance, the game will not recognize it while syncing and saving, and replace it with air. ::: Creating Blocks @@ -38,7 +42,7 @@ For simple blocks which need no special functionality (think cobblestone, wooden - `destroyTime` - Determines the time the block needs to be destroyed. - Stone has a destroy time of 1.5, dirt has 0.5, obsidian has 50, and bedrock has -1 (unbreakable). - `explosionResistance` - Determines the explosion resistance of the block. - - Stone has an explosion resistance of 6.0, dirt has 0.5, obsidian has 1200, and bedrock has 3600000. + - Stone has an explosion resistance of 6.0, dirt has 0.5, obsidian has 1,200, and bedrock has 3,600,000. - `sound` - Sets the sound the block makes when it is punched, broken, or placed. - The default value is `SoundType.STONE`. See the [Sounds page][sounds] for more details. - `lightLevel` - Sets the light emission of the block. Accepts a function with a `BlockState` parameter that returns a value between 0 and 15. @@ -68,7 +72,7 @@ A `BlockItem` must be registered separately from the block. This is because a bl Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a different hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; see the classes `Block`, `BlockBehaviour` and `IForgeBlock` for more information. See also the Using blocks section below for some of the most common use cases for blocks. -If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity][blockentities] should be used. The rule of thumb here is that if you have a finite amount of states, use blockstates, and if you have an infinite or near-infinite amount of states, use a block entity. +If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity][blockentities] should be used. The rule of thumb here is that if you have a finite and reasonably small amount of states (= a few hundred states at most), use blockstates, and if you have an infinite or near-infinite amount of states, use a block entity. ### Resources diff --git a/docs/blocks/states.md b/docs/blocks/states.md index fad159e69..c1ed1368b 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -44,6 +44,8 @@ Here, the rule of thumb is: **if you have a finite amount of states, use a block Blockstates and block entities can be used in conjunction with one another. For example, the chest uses blockstate properties for things like the direction, whether it is opened or not, or becoming a double chest is handled by blockstate properties, while storing the inventory or interacting with hoppers is handled by a block entity. +There is no definitive answer to the question "How many states are too much for a blockstate?", but the generally agreed upon answer is that if you need more than 8-9 bits of data (i.e. more than a few hundred states), use a block entity instead. + Implementing Blockstates ------------------------ @@ -130,7 +132,18 @@ To set a `BlockState` in the level, use `Level#setBlock(BlockPos, BlockState, in The `int` parameter deserves some extra explanation, as its meaning is not immediately obvious. It denotes what is known as update flags. -To help setting the update flags correctly, there are a number of `int` constants in `Block`, prefixed with `UPDATE_`. Examples include `Block.UPDATE_NEIGHBORS` or `Block.UPDATE_CLIENTS`. These constants can be bitwise-ORed together (for example `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`) if you wish to combine them. If you're unsure which one to use, use `Block.UPDATE_ALL`. +To help setting the update flags correctly, there are a number of `int` constants in `Block`, prefixed with `UPDATE_`. These constants can be bitwise-ORed together (for example `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`) if you wish to combine them. + +- `Block.UPDATE_NEIGHBORS` sends an update to the neighboring blocks. More specifically, it calls `Block#neighborChanged`, which calls a number of methods, most of which are redstone-related in some way. +- `Block.UPDATE_CLIENTS` syncs the block update to the client. +- `Block.UPDATE_INVISIBLE` explicitly does not update. This also overrules `Block.UPDATE_CLIENTS`, causing the update to not be synced. +- `Block.UPDATE_IMMEDIATE` forces the update immediately, instead of on the next tick. +- `Block.UPDATE_KNOWN_SHAPE` stops neighbor update recursion. +- `Block.UPDATE_SUPPRESS_DROPS` disables block drops for the old block at that position. +- `Block.UPDATE_MOVE_BY_PISTON` is only used by piston code to signalize that the block was moved by a piston. +- `Block.UPDATE_ALL` is an alias for `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`. +- `Block.UPDATE_ALL_IMMEDIATE` is an alias for `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS | Block.UPDATE_IMMEDIATE`. +- `Block.NONE` is an alias for `Block.UPDATE_INVISIBLE`. [block]: index.md [blockentity]: ../blockentities/index.md From 17c00980db1ffeb2f867adb14bbadecf76beb4e6 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Thu, 26 Oct 2023 19:09:30 +0200 Subject: [PATCH 14/27] implement feedback --- docs/blocks/index.md | 22 +++++++++++++--------- docs/blocks/states.md | 30 ++++++++++++++++++------------ 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 0a3c6d832..cb9fbb5fc 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -22,13 +22,13 @@ After registering the block, all references to the new `my_block` should use thi level.getBlockState(position).is(MyBlockRegistrationClass.MY_BLOCK.get()); ``` -This approach also has the convenient side effect that `block1 == block2` works and should be used instead of Java's `equals` method. +This approach also has the convenient effect that `block1 == block2` works and can be used instead of Java's `equals` method (using `equals` still works, of course, but is pointless since it compares by reference anyway). :::danger Do not call `new Block()` outside registration! As soon as you do that, things can and will break: - Blocks must be created while registries are unfrozen. NeoForge unfreezes registries for you and freezes them later, so registration is your time window to create blocks. -- If you try to create and/or register a block when registries are frozen again, the game will crash. On top of that, error messages are usually cryptic here, so it's best to avoid them. +- If you try to create and/or register a block when registries are frozen again, the game will crash and report a `null` block, which can be very confusing. - If you still manage to have a dangling block instance, the game will not recognize it while syncing and saving, and replace it with air. ::: @@ -53,11 +53,14 @@ For simple blocks which need no special functionality (think cobblestone, wooden So for example, a simple implementation would look something like this: ```java -public static final RegistryObject MY_BETTER_BLOCK = BLOCKS.register("my_better_block", () -> new Block(BlockBehaviour.Properties.of() - .destroyTime(2.0f) - .explosionResistance(10.0f) - .sound(SoundType.GRAVEL) - .lightLevel(state -> 7))); +public static final RegistryObject MY_BETTER_BLOCK = BLOCKS.register( + "my_better_block", + () -> new Block(BlockBehaviour.Properties.of() + .destroyTime(2.0f) + .explosionResistance(10.0f) + .sound(SoundType.GRAVEL) + .lightLevel(state -> 7) + )); ``` For further documentation, see the source code of `BlockBehaviour.Properties`. For more examples, or to look at the values used by Minecraft, have a look at the `Blocks` class. @@ -70,7 +73,7 @@ A `BlockItem` must be registered separately from the block. This is because a bl ### More Functionality -Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a different hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; see the classes `Block`, `BlockBehaviour` and `IForgeBlock` for more information. See also the Using blocks section below for some of the most common use cases for blocks. +Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a different hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; see the classes `Block`, `BlockBehaviour` and `IForgeBlock` for more information. See also the [Using blocks][usingblocks] section below for some of the most common use cases for blocks. If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity][blockentities] should be used. The rule of thumb here is that if you have a finite and reasonably small amount of states (= a few hundred states at most), use blockstates, and if you have an infinite or near-infinite amount of states, use a block entity. @@ -127,7 +130,7 @@ The following subsections further break down these stages into actual method cal #### The "Initiating" Stage -- `InputEvent.InteractionKeyMappingTriggered` is fired with the left mouse button and the main hand. If the event is canceled, the pipeline ends. +- Client-only: `InputEvent.InteractionKeyMappingTriggered` is fired with the left mouse button and the main hand. If the event is canceled, the pipeline ends. - Several prerequisites are checked, for example that you are not in spectator mode, that all required feature flags for the `ItemStack` in your main hand are enabled or that the block in question is not outside the world border. If at least one of these checks fails, the pipeline ends. - `PlayerInteractEvent.LeftClickBlock` is fired. If the event is canceled, the pipeline ends. - `Block#attack` is called. @@ -179,4 +182,5 @@ Random ticking is used by a wide range of mechanics in Minecraft, such as plant [registration]: ../concepts/registries.md#methods-for-registering [resources]: ../resources/client/index.md [sounds]: ../gameeffects/sounds.md +[usingblocks]: #using-blocks [usingblockstates]: states.md#using-blockstates diff --git a/docs/blocks/states.md b/docs/blocks/states.md index c1ed1368b..2caeef703 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -1,13 +1,13 @@ Blockstates =========== -Introduction ------------- - Often, you will find yourself in a situation where you want different states of a block. For example, a wheat crop has eight growth stages, and making a separate block for each stage feels wrong. Or you have a slab or slab-like block - one bottom state, one top state, and one state that has both. This is where blockstates come into play. Blockstates are an easy way to represent the different states a block can have, like a growth stage or a slab placement type. +Blockstate Properties +--------------------- + Blockstates use a system of properties. A block can have multiple properties of multiple types. For example, a lever has two properties: whether it is currently activated (`powered`, 2 options) and which direction it is placed in (`facing`, 6 options). So in total, the lever has 12 different blockstates: ``` @@ -29,7 +29,7 @@ The notation `blockid[property1=value1,property2=value,...]` is the standardized If your block does not have any blockstate properties defined, it still has exactly one blockstate - that is the one without any properties, since there are no properties to specify. This can be denoted as `minecraft:oak_planks[]` or simply `minecraft:oak_planks`. -As with blocks, every `BlockState` exists exactly once in memory. This has the convenient side effect that `==` can and should be used to compare `BlockState`s. `BlockState` is also a final class, meaning it cannot be extended. **Any functionality goes in the corresponding [Block][block] class!** +As with blocks, every `BlockState` exists exactly once in memory. This means that `==` can and should be used to compare `BlockState`s. `BlockState` is also a final class, meaning it cannot be extended. **Any functionality goes in the corresponding [Block][block] class!** When to Use Blockstates ----------------------- @@ -44,7 +44,7 @@ Here, the rule of thumb is: **if you have a finite amount of states, use a block Blockstates and block entities can be used in conjunction with one another. For example, the chest uses blockstate properties for things like the direction, whether it is opened or not, or becoming a double chest is handled by blockstate properties, while storing the inventory or interacting with hoppers is handled by a block entity. -There is no definitive answer to the question "How many states are too much for a blockstate?", but the generally agreed upon answer is that if you need more than 8-9 bits of data (i.e. more than a few hundred states), use a block entity instead. +There is no definitive answer to the question "How many states are too much for a blockstate?", but the authors recommend that if you need more than 8-9 bits of data (i.e. more than a few hundred states), you should use a block entity instead. Implementing Blockstates ------------------------ @@ -78,13 +78,16 @@ To further illustrate this, this is what the relevant bits of the `LeverBlock` c ```java public class LeverBlock extends Block { - // Note: It is possible to directly use the values in BlockStateProperties instead of referencing them here again. However, for the sake of simplicity and readability, it is recommended to add constants like this. + // Note: It is possible to directly use the values in BlockStateProperties instead of referencing them here again. + // However, for the sake of simplicity and readability, it is recommended to add constants like this. public static final DirectionProperty FACING = BlockStateProperties.FACING; public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public LeverBlock(BlockBehaviour.Properties pProperties) { super(pProperties); - registerDefaultState(stateDefinition.any() // stateDefinition.any() returns a random BlockState from an internal set, we don't care because we're setting all values ourselves anyway + // stateDefinition.any() returns a random BlockState from an internal set, + // we don't care because we're setting all values ourselves anyway + registerDefaultState(stateDefinition.any() .setValue(FACING, Direction.NORTH) .setValue(POWERED, false) ); @@ -92,13 +95,15 @@ public class LeverBlock extends Block { @Override protected void createBlockStateDefinition(StateDefinition.Builder pBuilder) { - pBuilder.add(FACING, POWERED); // this is where the properties are actually added to the state + // this is where the properties are actually added to the state + pBuilder.add(FACING, POWERED); } @Override @Nullable public BlockState getStateForPlacement(BlockPlaceContext pContext) { - // code that determines which state will be used when placing down this block, depending on the BlockPlaceContext + // code that determines which state will be used when + // placing down this block, depending on the BlockPlaceContext } } ``` @@ -111,6 +116,7 @@ To go from `Block` to `BlockState`, call `Block#defaultBlockState()`. The defaul You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. Reusing our lever example, this would look something like this: ```java +// LeverBlock.FACING is a DirectionProperty and thus can be used to obtain a Direction from the BlockState Direction direction = leverBlockState.getValue(LeverBlock.FACING); ``` @@ -136,11 +142,11 @@ To help setting the update flags correctly, there are a number of `int` constant - `Block.UPDATE_NEIGHBORS` sends an update to the neighboring blocks. More specifically, it calls `Block#neighborChanged`, which calls a number of methods, most of which are redstone-related in some way. - `Block.UPDATE_CLIENTS` syncs the block update to the client. -- `Block.UPDATE_INVISIBLE` explicitly does not update. This also overrules `Block.UPDATE_CLIENTS`, causing the update to not be synced. -- `Block.UPDATE_IMMEDIATE` forces the update immediately, instead of on the next tick. +- `Block.UPDATE_INVISIBLE` explicitly does not update on the client. This also overrules `Block.UPDATE_CLIENTS`, causing the update to not be synced. The block is always updated on the server. +- `Block.UPDATE_IMMEDIATE` forces a re-render on the main thread. - `Block.UPDATE_KNOWN_SHAPE` stops neighbor update recursion. - `Block.UPDATE_SUPPRESS_DROPS` disables block drops for the old block at that position. -- `Block.UPDATE_MOVE_BY_PISTON` is only used by piston code to signalize that the block was moved by a piston. +- `Block.UPDATE_MOVE_BY_PISTON` is only used by piston code to signalize that the block was moved by a piston. This is mainly responsible for delaying light engine updates. - `Block.UPDATE_ALL` is an alias for `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`. - `Block.UPDATE_ALL_IMMEDIATE` is an alias for `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS | Block.UPDATE_IMMEDIATE`. - `Block.NONE` is an alias for `Block.UPDATE_INVISIBLE`. From b6741fd0578e841b556a5621d78b71d9c2ea9bfb Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Thu, 26 Oct 2023 19:27:42 +0200 Subject: [PATCH 15/27] implement more feedback --- docs/blocks/index.md | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index cb9fbb5fc..4b7fbf973 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -88,7 +88,7 @@ Using Blocks Blocks are very rarely directly used to do things. In fact, probably two of the most common operations in all of Minecraft - getting the block at a position, and setting a block at a position - use blockstates, not blocks. The general design approach is to have the block define behavior, but have the behavior actually run through blockstates. Due to this, `BlockState`s are often passed to methods of `Block` as a parameter. For more information on how blockstates are used, and on how to get one from a block, see [Using Blockstates][usingblockstates]. -In several situations, multiple methods of `Block` are used at different times. The following subsections list the most common block-related pipelines. Unless specified otherwise, all methods are called on both logical sides. +In several situations, multiple methods of `Block` are used at different times. The following subsections list the most common block-related pipelines. Unless specified otherwise, all methods are called on both logical sides and should return the same result on both sides. ### Placing a Block @@ -153,25 +153,37 @@ The following subsections further break down these stages into actual method cal - In that `Level#setBlock` call, `Block#onRemove` is called. - `Block#destroy` is called. - Server-only: If the previous call to `IForgeBlock#canHarvestBlock` returned `true`, `Block#playerDestroy` is called. -- Server-onlĂ˝: `IForgeBlock#getExpDrop` is called. +- Server-only: `IForgeBlock#getExpDrop` is called. - Server-only: `Block#popExperience` is called with the result of the previous `IForgeBlock#getExpDrop` call, if that call returned a value greater than 0. #### The "Finishing" Stage - The internal destroy progress counter is reset. -### Ticking and Random Ticking +### Ticking -Like many other things, blocks are ticked (updated) every tick, which is 1 / 20 of a second, or 50 milliseconds. +Ticking is a mechanism that updates (ticks) parts of the game every 1 / 20 seconds, or 50 milliseconds ("one tick"). Blocks provide different ticking methods that are called in different ways. -There are two methods for ticking: `Block#tick` and `Block#animateTick`. The difference is that `Block#tick` is called only on the server, whereas `Block#animateTick` is called only on the client. For example, redstone updates are processed in `Block#tick`, while the fire particles of torches are spawned in `Block#animateTick`. Override either of them to add your server/client ticking behavior. +#### Server Ticking and Tick Scheduling -Alongside ticking, there is a separate "weather tick", if you will. The method `Block#handlePrecipitation` is called only on the server, only when it is raining in some form, with a 1 in 16 chance. This is used for example by cauldrons that fill during rain or snowfall. +`Block#tick` is called in two occasions: either through default [random ticking][randomtick] (see below), or through scheduled ticks. Scheduled ticks can be created through `Level#scheduleTick(BlockPos, Block, int)`, where the `int` denotes a delay. This is used in various placed by vanilla, for example, the tilting mechanism of big dripleaves heavily relies on this system. Other prominent users are various redstone components. -And finally, there is the random tick system. Random ticks must be enabled through the `BlockBehaviour.Properties` of the block by calling the `BlockBehaviour.Properties#randomTicks()` method. This enables the block to be part of the random ticking mechanic. +#### Client Ticking + +`Block#animateTick` is called exclusively on the client, every frame. This is where client-only behavior, for example the torch particle spawning, happens. + +#### Weather Ticking + +Weather ticking is handled by `Block#handlePrecipitation` and runs independent of regular ticking. It is called only on the server, only when it is raining in some form, with a 1 in 16 chance. This is used for example by cauldrons that fill during rain or snowfall. + +#### Random Ticking + +The random tick system runs independent of regular ticking. Random ticks must be enabled through the `BlockBehaviour.Properties` of the block by calling the `BlockBehaviour.Properties#randomTicks()` method. This enables the block to be part of the random ticking mechanic. Random ticks occur every tick for a set amount of blocks in a chunk. That set amount is defined through the `randomTickSpeed` gamerule. With its default value of 3, every tick, 3 random blocks from the chunk are chosen. If these blocks have random ticking enabled, then their respective `Block#randomTick` methods are called. +`Block#randomTick` by default calls `Block#tick`, which is what should normally be overridden. `Block#randomTick` should only be overridden if you specifically want different behavior for random ticking and regular (scheduled) ticking. + Random ticking is used by a wide range of mechanics in Minecraft, such as plant growth, ice and snow melting, or copper oxidizing. [blockentities]: ../blockentities/index.md @@ -179,6 +191,7 @@ Random ticking is used by a wide range of mechanics in Minecraft, such as plant [events]: ../concepts/events.md [interactionpipeline]: ../items/interactionpipeline.md [item]: ../items/index.md +[randomtick]: #random-ticking [registration]: ../concepts/registries.md#methods-for-registering [resources]: ../resources/client/index.md [sounds]: ../gameeffects/sounds.md From 55c37f5d0f78524fc47c679efa2378dc4f14ba4e Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Thu, 26 Oct 2023 20:10:38 +0200 Subject: [PATCH 16/27] add extra disclaimer about PlayerInteractEvent.LeftClickBlock --- docs/blocks/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 4b7fbf973..bf8b244c7 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -133,11 +133,15 @@ The following subsections further break down these stages into actual method cal - Client-only: `InputEvent.InteractionKeyMappingTriggered` is fired with the left mouse button and the main hand. If the event is canceled, the pipeline ends. - Several prerequisites are checked, for example that you are not in spectator mode, that all required feature flags for the `ItemStack` in your main hand are enabled or that the block in question is not outside the world border. If at least one of these checks fails, the pipeline ends. - `PlayerInteractEvent.LeftClickBlock` is fired. If the event is canceled, the pipeline ends. + - Note that when the event is canceled on the client, no packets are sent to the server and thus no logic runs on the server. + - However, canceling this event on the server will still cause client code to run, which can lead to desyncs! - `Block#attack` is called. #### The "Mining" Stage - `PlayerInteractEvent.LeftClickBlock` is fired. If the event is canceled, the pipeline moves to the "finishing" stage. + - Note that when the event is canceled on the client, no packets are sent to the server and thus no logic runs on the server. + - However, canceling this event on the server will still cause client code to run, which can lead to desyncs! - `Block#getDestroyProgress` is called and added to the internal destroy progress counter. - `Block#getDestroyProgress` returns a float value between 0 and 1, representing how much the destroy progress counter should be increased every tick. - The progress overlay (cracking texture) is updated accordingly. From a3090aa67beb3b704c95977f51fde4c217cc708c Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Thu, 26 Oct 2023 20:12:53 +0200 Subject: [PATCH 17/27] add highlights to codeblocks --- docs/blocks/index.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index bf8b244c7..7fd744517 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -18,8 +18,9 @@ public static final RegistryObject MY_BLOCK = BLOCKS.register("my_block", After registering the block, all references to the new `my_block` should use this constant. For example, if you want to check if the block at a given position is `my_block`, the code for that would look something like this: ```java -//level.getBlockState(position) returns the blockstate placed in the given level (world) at the given position -level.getBlockState(position).is(MyBlockRegistrationClass.MY_BLOCK.get()); +level.getBlockState(position) // returns the blockstate placed in the given level (world) at the given position + //highlight-next-line + .is(MyBlockRegistrationClass.MY_BLOCK.get()); ``` This approach also has the convenient effect that `block1 == block2` works and can be used instead of Java's `equals` method (using `equals` still works, of course, but is pointless since it compares by reference anyway). @@ -56,10 +57,12 @@ So for example, a simple implementation would look something like this: public static final RegistryObject MY_BETTER_BLOCK = BLOCKS.register( "my_better_block", () -> new Block(BlockBehaviour.Properties.of() + //highlight-start .destroyTime(2.0f) .explosionResistance(10.0f) .sound(SoundType.GRAVEL) .lightLevel(state -> 7) + //highlight-end )); ``` From 27f5fd51fca0ae6def68742a4ba8036d6489a8e4 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 <52419336+IchHabeHunger54@users.noreply.github.com> Date: Wed, 15 Nov 2023 12:47:07 +0100 Subject: [PATCH 18/27] Update docs/blocks/states.md Co-authored-by: ChampionAsh5357 --- docs/blocks/states.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blocks/states.md b/docs/blocks/states.md index 2caeef703..5e190f748 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -44,7 +44,7 @@ Here, the rule of thumb is: **if you have a finite amount of states, use a block Blockstates and block entities can be used in conjunction with one another. For example, the chest uses blockstate properties for things like the direction, whether it is opened or not, or becoming a double chest is handled by blockstate properties, while storing the inventory or interacting with hoppers is handled by a block entity. -There is no definitive answer to the question "How many states are too much for a blockstate?", but the authors recommend that if you need more than 8-9 bits of data (i.e. more than a few hundred states), you should use a block entity instead. +There is no definitive answer to the question "How many states are too much for a blockstate?", but we recommend that if you need more than 8-9 bits of data (i.e. more than a few hundred states), you should use a block entity instead. Implementing Blockstates ------------------------ From f510e01e2adaca160e981b0d6ad79a40a9f6b1d5 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Wed, 15 Nov 2023 13:46:55 +0100 Subject: [PATCH 19/27] shorten interactionpipeline.md --- docs/items/interactionpipeline.md | 78 +++++++------------------------ 1 file changed, 17 insertions(+), 61 deletions(-) diff --git a/docs/items/interactionpipeline.md b/docs/items/interactionpipeline.md index 7cf3edf6c..5db916001 100644 --- a/docs/items/interactionpipeline.md +++ b/docs/items/interactionpipeline.md @@ -32,84 +32,40 @@ When you right-click anywhere in the world, a number of things happen, depending Result Types ------------ -There are two different types of results: `InteractionResult`s and `InteractionResultHolder`s. Depending on the situation, one of the two is used. +There are two different types of results: `InteractionResult`s and `InteractionResultHolder`s. `InteractionResult` is used most of the time, only `Item#use` uses `InteractionResultHolder`. `InteractionResult` is an enum consisting of five values: `SUCCESS`, `CONSUME`, `CONSUME_PARTIAL`, `PASS` and `FAIL`. Additionally, the method `InteractionResult#sidedSuccess` is available, which returns `SUCCESS` on the server and `CONSUME` on the client. `InteractionResultHolder` is a wrapper around `InteractionResult` that adds additional context for `T`. `T` can be anything, but in 99.99 percent of cases, it is an `ItemStack`. `InteractionResultHolder` provides wrapper methods for the enum values (`#success`, `#consume`, `#pass` and `#fail`), as well as `#sidedSuccess`, which calls `#success` on the server and `#consume` on the client. -`Entity#interactAt` -------------------- +Generally, the different values mean the following: -The return type is `InteractionResult`. +- `InteractionResult#sidedSuccess` (or `InteractionResultHolder#sidedSuccess` where needed) should be used if the operation should be considered successful, and you want the arm to swing. The pipeline will end. +- `InteractionResult.SUCCESS` (or `InteractionResultHolder#success` where needed) should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. The pipeline will end. +- `InteractionResult.CONSUME` (or `InteractionResultHolder#consume` where needed) should be used if the operation should be considered successful, but you do not want the arm to swing. The pipeline will end. +- `InteractionResult.CONSUME_PARTIAL` is mostly identical to `InteractionResult.CONSUME`, the only difference is in its usage in [`Item#useOn`][itemuseon]. +- `InteractionResult.FAIL` (or `InteractionResultHolder#fail` where needed) should be used if the item functionality should be considered failed and no further interaction should be performed. The pipeline will end. This should only be used in `Item#useOn` and `Item#use`, all other implementations should use `InteractionResult.PASS` to allow item behavior to still be called. +- `InteractionResult.PASS` (or `InteractionResultHolder#pass` where needed) should be used if the operation should be considered neither successful nor failed. The pipeline will continue. This is the default behavior (unless otherwise specified). -- `InteractionResult#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. -- `InteractionResult.SUCCESS` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. -- `InteractionResult.CONSUME` should be used if the operation should be considered successful, but you do not want the arm to swing. -- `InteractionResult.FAIL` should be used if the item functionality should be considered failed and no further interaction should be performed. **In most cases, this can be replaced with `PASS`!** -- `InteractionResult.PASS` should be used if the operation should be considered neither successful nor failed. The pipeline will continue to evaluate `Entity#interact`. This is the default behavior of this method. - -`Entity#interact` and `Mob#mobInteract` ---------------------------------------- - -The return type is `InteractionResult`. - -- `InteractionResult#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. -- `InteractionResult.SUCCESS` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. -- `InteractionResult.CONSUME` should be used if the operation should be considered successful, but you do not want the arm to swing. -- `InteractionResult.FAIL` should be used if the item functionality should be considered failed and no further interaction should be performed. **In most cases, this can be replaced with `PASS`!** -- `InteractionResult.PASS` should be used if the operation should be considered neither successful nor failed. The pipeline will continue to evaluate `Item#interactLivingEntity`. This is the default behavior of this method. - -`Item#interactLivingEntity` ---------------------------- - -The return type is `InteractionResult`. - -- `InteractionResult#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. -- `InteractionResult.SUCCESS` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. -- `InteractionResult.CONSUME` should be used if the operation should be considered successful, but you do not want the arm to swing. -- `InteractionResult.FAIL` should be used if the item functionality should be considered failed and no further interaction should be performed. **In most cases, this can be replaced with `PASS`!** -- `InteractionResult.PASS` should be used if the operation should be considered neither successful nor failed. The pipeline will continue to evaluate `Item#use`. This is the default behavior of this method. +Some methods have special behavior or requirements, which are explained in the below chapters. `IForgeItem#onItemUseFirst` --------------------------- -The return type is `InteractionResult`. - -- `InteractionResult.SUCCESS` should be used if the item functionality should be considered successful and no further interaction should be performed. -- `InteractionResult.FAIL` should be used if the item functionality should be considered failed and no further interaction should be performed. -- `InteractionResult.PASS` should be used if the item functionality should be considered neither successful nor failed. The pipeline will continue to evaluate `Block#use`. This is the default behavior of this method. - -`Block#use` ------------ - -The return type is `InteractionResult`. - -- `InteractionResult#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. -- `InteractionResult.SUCCESS` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. -- `InteractionResult.CONSUME` should be used if the operation should be considered successful, but you do not want the arm to swing. -- `InteractionResult.FAIL` should be used if the item functionality should be considered failed and no further interaction should be performed. **In most cases, this can be replaced with `PASS`!** -- `InteractionResult.PASS` should be used if the operation should be considered neither successful nor failed. The pipeline will continue to evaluate `Item#useOn`. This is the default behavior of this method. +`InteractionResult#sidedSuccess` and `InteractionResult.CONSUME` don't have an effect here. Only `InteractionResult.SUCCESS`, `InteractionResult.FAIL` or `InteractionResult.PASS` should be used here. `Item#useOn` ------------ -The return type is `InteractionResult`. - -- `InteractionResult#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. -- `InteractionResult.SUCCESS` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. -- `InteractionResult.CONSUME` should be used if the operation should be considered successful, but you do not want the arm to swing. -- `InteractionResult.CONSUME_PARTIAL` should be used if the operation should be considered successful, but you do not want the arm to swing or an `ITEM_USED` stat point to be awarded. -- `InteractionResult.FAIL` should be used if the operation should be considered failed and no further interaction should be performed. -- `InteractionResult.PASS` should be used if the operation should be considered neither successful nor failed. The pipeline will continue to evaluate `Item#use`. This is the default behavior of this method. +If you want the operation to be considered successful, but you do not want the arm to swing or an `ITEM_USED` stat point to be awarded, use `InteractionResult.CONSUME_PARTIAL`. `Item#use` ---------- -The return type is `InteractionResultHolder`. The resulting `ItemStack` in the `InteractionResultHolder` replaces the `ItemStack` the usage was initiated with, if it has changed. The default implementation of `Item#use` returns `InteractionResultHolder#consume` when the item is edible and the player can eat the item (because they are hungry, or because the item is always edible), `InteractionResultHolder#fail` when the item is edible but the player cannot eat the item, and `InteractionResultHolder#pass` if the item is not edible. +This is the only instance where the return type is `InteractionResultHolder`. The resulting `ItemStack` in the `InteractionResultHolder` replaces the `ItemStack` the usage was initiated with, if it has changed. + +The default implementation of `Item#use` returns `InteractionResultHolder#consume` when the item is edible and the player can eat the item (because they are hungry, or because the item is always edible), `InteractionResultHolder#fail` when the item is edible but the player cannot eat the item, and `InteractionResultHolder#pass` if the item is not edible. + +Returning `InteractionResultHolder#fail` here while considering the main hand will prevent offhand behavior from running. If you want offhand behavior to run (which you usually want), return `InteractionResultHolder#pass` instead. -- `InteractionResultHolder#sidedSuccess` should be used if the operation should be considered successful, and you want the arm to swing. -- `InteractionResultHolder#success` should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. -- `InteractionResultHolder#consume` should be used if the operation should be considered successful, but you do not want the arm to swing. -- `InteractionResultHolder#fail` should be used if the operation should be considered failed and no further interaction should be performed. -- `InteractionResultHolder#pass` should be used if the operation should be considered neither successful nor failed. This will end the pipeline for this hand, but may run the pipeline for the other hand if applicable. +[itemuseon]: #itemuseon From d7662bd939bc27b5a280fd7a62ffa7eb9cd4d3c9 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Wed, 15 Nov 2023 17:16:10 +0100 Subject: [PATCH 20/27] fix a grammar mistake in states.md --- docs/blocks/states.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blocks/states.md b/docs/blocks/states.md index 5e190f748..00648bb15 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -42,7 +42,7 @@ A good rule of thumb is: **if it has a different name, it should be a separate b Here, the rule of thumb is: **if you have a finite amount of states, use a blockstate, if you have an infinite or near-infinite amount of states, use a block entity.** Block entities can store arbitrary amounts of data, but are slower than blockstates. -Blockstates and block entities can be used in conjunction with one another. For example, the chest uses blockstate properties for things like the direction, whether it is opened or not, or becoming a double chest is handled by blockstate properties, while storing the inventory or interacting with hoppers is handled by a block entity. +Blockstates and block entities can be used in conjunction with one another. For example, the chest uses blockstate properties for things like the direction, whether it is opened or not, or becoming a double chest, while storing the inventory or interacting with hoppers is handled by a block entity. There is no definitive answer to the question "How many states are too much for a blockstate?", but we recommend that if you need more than 8-9 bits of data (i.e. more than a few hundred states), you should use a block entity instead. From 06b95e2289d8c3390173ead3003084802ad00487 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 <52419336+IchHabeHunger54@users.noreply.github.com> Date: Thu, 16 Nov 2023 00:17:58 +0100 Subject: [PATCH 21/27] Update docs/blocks/states.md Co-authored-by: ChampionAsh5357 --- docs/blocks/states.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blocks/states.md b/docs/blocks/states.md index 00648bb15..09ea4cf02 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -36,7 +36,7 @@ When to Use Blockstates ### Blockstates vs. Separate Blocks -A good rule of thumb is: **if it has a different name, it should be a separate block**. An example is making chair blocks: the direction of the chair should be a property, while the different types of wood should be separated into different blocks. So you'd have one chair block for each wood type, and each chair block has four blockstates (one for each direction). +A good rule of thumb is: **if it has a different name, it should be a separate block**. An example is making chair blocks: the direction of the chair should be a property, while the different types of wood should be separated into different blocks. So you'd have one chair block for each wood type, and each chair block has four blockstates (one for each direction). ### Blockstates vs. [Block Entities][blockentity] From 0b9ce65d6578b274455dc7b637dcae1a7ccb1eee Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Mon, 20 Nov 2023 16:46:25 +0100 Subject: [PATCH 22/27] implement requested feedback --- docs/blocks/index.md | 20 ++++++------- docs/blocks/states.md | 48 +++++++++++++++---------------- docs/items/interactionpipeline.md | 6 ++-- 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 7fd744517..c82c76ab2 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -76,7 +76,7 @@ A `BlockItem` must be registered separately from the block. This is because a bl ### More Functionality -Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a different hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; see the classes `Block`, `BlockBehaviour` and `IForgeBlock` for more information. See also the [Using blocks][usingblocks] section below for some of the most common use cases for blocks. +Directly using `Block` only allows for very basic blocks. If you want to add functionality, like player interaction or a different hitbox, a custom class that extends `Block` is required. The `Block` class has many methods that can be overridden to do different things; see the classes `Block`, `BlockBehaviour` and `IBlockExtension` for more information. See also the [Using blocks][usingblocks] section below for some of the most common use cases for blocks. If you want to make a block that has different variants (think a slab that has a bottom, top, and double variant), you should use [blockstates]. And finally, if you want a block that stores additional data (think a chest that stores its inventory), a [block entity][blockentities] should be used. The rule of thumb here is that if you have a finite and reasonably small amount of states (= a few hundred states at most), use blockstates, and if you have an infinite or near-infinite amount of states, use a block entity. @@ -97,9 +97,9 @@ In several situations, multiple methods of `Block` are used at different times. Block placement logic is called from `BlockItem#useOn` (or some subclass's implementation thereof, such as in `PlaceOnWaterBlockItem`, which is used for lily pads). For more information on how the game gets there, see the [Interaction Pipeline][interactionpipeline]. In practice, this means that as soon as a `BlockItem` is right-clicked (for example a cobblestone item), this behavior is called. -- Several prerequisites are checked, for example that you are not in spectator mode, that all required feature flags for the block are enabled or that the block in question is not outside the world border. If at least one of these checks fails, the pipeline ends. -- `Block#canBeReplaced` is called for the block currently at the position where the block is tried to place. If it returns `false`, the pipeline ends. -- `Block#getStateForPlacement` is called. +- Several prerequisites are checked, for example that you are not in spectator mode, that all required feature flags for the block are enabled or that the target position is not outside the world border. If at least one of these checks fails, the pipeline ends. +- `Block#canBeReplaced` is called for the block currently at the position where the block is attempted to be placed. If it returns `false`, the pipeline ends. Prominent cases that return `true` here are tall grass or snow layers. +- `Block#getStateForPlacement` is called. This is where, depending on the context (which includes information like the position, the rotation and the side the block is placed on), different block states can be returned. This is useful for example for blocks that can be placed in different directions. - `Block#canSurvive` is called with the blockstate obtained in the previous step. If it returns `false`, the pipeline ends. - The blockstate is set into the level via a `Level#setBlock` call. - In that `Level#setBlock` call, `Block#onPlace` is called. @@ -152,16 +152,16 @@ The following subsections further break down these stages into actual method cal #### The "Actually Breaking" Stage -- `Item#onBlockStartBreak` is called. If it returns `true`, the pipeline moves to the "finishing" stage. -- Server-only: `IForgeBlock#canHarvestBlock` is called. +- `Item#onBlockStartBreak` is called. If it returns `true` (determining that the block should not be broken), the pipeline moves to the "finishing" stage. +- Server-only: `IBlockExtension#canHarvestBlock` is called. This determines whether the block can be harvested, i.e. broken with drops. - `Block#onDestroyedByPlayer` is called. If it returns `false`, the pipeline moves to the "finishing" stage. In that `Block#onDestroyedByPlayer` call: - `Block#playerWillDestroy` is called. - The blockstate is removed from the level via a `Level#setBlock` call with `Blocks.AIR.defaultBlockState()` as the blockstate parameter. - In that `Level#setBlock` call, `Block#onRemove` is called. - `Block#destroy` is called. -- Server-only: If the previous call to `IForgeBlock#canHarvestBlock` returned `true`, `Block#playerDestroy` is called. -- Server-only: `IForgeBlock#getExpDrop` is called. -- Server-only: `Block#popExperience` is called with the result of the previous `IForgeBlock#getExpDrop` call, if that call returned a value greater than 0. +- Server-only: If the previous call to `IBlockExtension#canHarvestBlock` returned `true`, `Block#playerDestroy` is called. +- Server-only: `IBlockExtension#getExpDrop` is called. +- Server-only: `Block#popExperience` is called with the result of the previous `IBlockExtension#getExpDrop` call, if that call returned a value greater than 0. #### The "Finishing" Stage @@ -173,7 +173,7 @@ Ticking is a mechanism that updates (ticks) parts of the game every 1 / 20 secon #### Server Ticking and Tick Scheduling -`Block#tick` is called in two occasions: either through default [random ticking][randomtick] (see below), or through scheduled ticks. Scheduled ticks can be created through `Level#scheduleTick(BlockPos, Block, int)`, where the `int` denotes a delay. This is used in various placed by vanilla, for example, the tilting mechanism of big dripleaves heavily relies on this system. Other prominent users are various redstone components. +`Block#tick` is called in two occasions: either through default [random ticking][randomtick] (see below), or through scheduled ticks. Scheduled ticks can be created through `Level#scheduleTick(BlockPos, Block, int)`, where the `int` denotes a delay. This is used in various places by vanilla, for example, the tilting mechanism of big dripleaves heavily relies on this system. Other prominent users are various redstone components. #### Client Ticking diff --git a/docs/blocks/states.md b/docs/blocks/states.md index 00648bb15..327537c11 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -8,21 +8,17 @@ This is where blockstates come into play. Blockstates are an easy way to represe Blockstate Properties --------------------- -Blockstates use a system of properties. A block can have multiple properties of multiple types. For example, a lever has two properties: whether it is currently activated (`powered`, 2 options) and which direction it is placed in (`facing`, 6 options). So in total, the lever has 12 different blockstates: +Blockstates use a system of properties. A block can have multiple properties of multiple types. For example, an end portal frame has two properties: whether it has an eye (`eye`, 2 options) and which direction it is placed in (`facing`, 4 options). So in total, the end portal frame has 8 (2 * 4) different blockstates: ``` -minecraft:lever[facing=north,powered=false] -minecraft:lever[facing=east,powered=false] -minecraft:lever[facing=south,powered=false] -minecraft:lever[facing=west,powered=false] -minecraft:lever[facing=up,powered=false] -minecraft:lever[facing=down,powered=false] -minecraft:lever[facing=north,powered=true] -minecraft:lever[facing=east,powered=true] -minecraft:lever[facing=south,powered=true] -minecraft:lever[facing=west,powered=true] -minecraft:lever[facing=up,powered=true] -minecraft:lever[facing=down,powered=true] +minecraft:end_portal_frame[facing=north,eye=false] +minecraft:end_portal_frame[facing=east,eye=false] +minecraft:end_portal_frame[facing=south,eye=false] +minecraft:end_portal_frame[facing=west,eye=false] +minecraft:end_portal_frame[facing=north,eye=true] +minecraft:end_portal_frame[facing=east,eye=true] +minecraft:end_portal_frame[facing=south,eye=true] +minecraft:end_portal_frame[facing=west,eye=true] ``` The notation `blockid[property1=value1,property2=value,...]` is the standardized way of representing a blockstate in text form, and is used in some locations in vanilla, for example in commands. @@ -42,7 +38,7 @@ A good rule of thumb is: **if it has a different name, it should be a separate b Here, the rule of thumb is: **if you have a finite amount of states, use a blockstate, if you have an infinite or near-infinite amount of states, use a block entity.** Block entities can store arbitrary amounts of data, but are slower than blockstates. -Blockstates and block entities can be used in conjunction with one another. For example, the chest uses blockstate properties for things like the direction, whether it is opened or not, or becoming a double chest, while storing the inventory or interacting with hoppers is handled by a block entity. +Blockstates and block entities can be used in conjunction with one another. For example, the chest uses blockstate properties for things like the direction, whether it is waterlogged or not, or becoming a double chest, while storing the inventory, whether it is currently open or not, or interacting with hoppers is handled by a block entity. There is no definitive answer to the question "How many states are too much for a blockstate?", but we recommend that if you need more than 8-9 bits of data (i.e. more than a few hundred states), you should use a block entity instead. @@ -74,14 +70,14 @@ Every block will also have a default state. If nothing else is specified, the de If you wish to change which `BlockState` is used when placing your block, override `Block#getStateForPlacement(BlockPlaceContext)`. This can be used to, for example, set the direction of your block depending on where the player is standing or looking when they place it. -To further illustrate this, this is what the relevant bits of the `LeverBlock` class look like: +To further illustrate this, this is what the relevant bits of the `EndPortalFrameBlock` class look like: ```java -public class LeverBlock extends Block { +public class EndPortalFrameBlock extends Block { // Note: It is possible to directly use the values in BlockStateProperties instead of referencing them here again. // However, for the sake of simplicity and readability, it is recommended to add constants like this. public static final DirectionProperty FACING = BlockStateProperties.FACING; - public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty EYE = BlockStateProperties.EYE; public LeverBlock(BlockBehaviour.Properties pProperties) { super(pProperties); @@ -89,14 +85,14 @@ public class LeverBlock extends Block { // we don't care because we're setting all values ourselves anyway registerDefaultState(stateDefinition.any() .setValue(FACING, Direction.NORTH) - .setValue(POWERED, false) + .setValue(EYE, false) ); } @Override protected void createBlockStateDefinition(StateDefinition.Builder pBuilder) { // this is where the properties are actually added to the state - pBuilder.add(FACING, POWERED); + pBuilder.add(FACING, EYE); } @Override @@ -113,17 +109,17 @@ Using Blockstates To go from `Block` to `BlockState`, call `Block#defaultBlockState()`. The default blockstate can be changed through `Block#registerDefaultState`, as described above. -You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. Reusing our lever example, this would look something like this: +You can get the value of a property by calling `BlockState#getValue(Property)`, passing it the property you want to get the value of. Reusing our end portal frame example, this would look something like this: ```java -// LeverBlock.FACING is a DirectionProperty and thus can be used to obtain a Direction from the BlockState -Direction direction = leverBlockState.getValue(LeverBlock.FACING); +// EndPortalFrameBlock.FACING is a DirectionProperty and thus can be used to obtain a Direction from the BlockState +Direction direction = endPortalFrameBlockState.getValue(EndPortalFrameBlock.FACING); ``` If you want to get a `BlockState` with a different set of values, simply call `BlockState#setValue(Property, T)` on an existing block state with the property and its value. With our lever, this goes something like this: ```java -leverBlockState = leverBlockState.setValue(LeverBlock.FACING, Direction.SOUTH); +endPortalFrameBlockState = endPortalFrameBlockState.setValue(EndPortalFrameBlock.FACING, Direction.SOUTH); ``` :::note @@ -143,13 +139,15 @@ To help setting the update flags correctly, there are a number of `int` constant - `Block.UPDATE_NEIGHBORS` sends an update to the neighboring blocks. More specifically, it calls `Block#neighborChanged`, which calls a number of methods, most of which are redstone-related in some way. - `Block.UPDATE_CLIENTS` syncs the block update to the client. - `Block.UPDATE_INVISIBLE` explicitly does not update on the client. This also overrules `Block.UPDATE_CLIENTS`, causing the update to not be synced. The block is always updated on the server. -- `Block.UPDATE_IMMEDIATE` forces a re-render on the main thread. +- `Block.UPDATE_IMMEDIATE` forces a re-render on the client's main thread. - `Block.UPDATE_KNOWN_SHAPE` stops neighbor update recursion. - `Block.UPDATE_SUPPRESS_DROPS` disables block drops for the old block at that position. -- `Block.UPDATE_MOVE_BY_PISTON` is only used by piston code to signalize that the block was moved by a piston. This is mainly responsible for delaying light engine updates. +- `Block.UPDATE_MOVE_BY_PISTON` is only used by piston code to signal that the block was moved by a piston. This is mainly responsible for delaying light engine updates. - `Block.UPDATE_ALL` is an alias for `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS`. - `Block.UPDATE_ALL_IMMEDIATE` is an alias for `Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS | Block.UPDATE_IMMEDIATE`. - `Block.NONE` is an alias for `Block.UPDATE_INVISIBLE`. +There is also a convenience method `Level#setBlockAndUpdate(BlockPos pos, BlockState state)` that calls `setBlock(pos, state, Block.UPDATE_ALL)` internally. + [block]: index.md [blockentity]: ../blockentities/index.md diff --git a/docs/items/interactionpipeline.md b/docs/items/interactionpipeline.md index 5db916001..8f05f0aeb 100644 --- a/docs/items/interactionpipeline.md +++ b/docs/items/interactionpipeline.md @@ -23,7 +23,7 @@ When you right-click anywhere in the world, a number of things happen, depending - If the entity you are looking at is a `LivingEntity`, `Item#interactLivingEntity` is called on the `ItemStack` in your main hand. If it returns a definitive result, the pipeline ends. - If you are looking at a block that is within your reach and not outside the world border: - `PlayerInteractEvent.RightClickBlock` is fired. If the event is canceled, the pipeline ends. You may also specifically deny only block or item usage in this event. - - `IForgeItem#onItemUseFirst` is called. If it returns a definitive result, the pipeline ends. + - `IItemExtension#onItemUseFirst` is called. If it returns a definitive result, the pipeline ends. - If the player is not sneaking and the event does not deny block usage, `Block#use` is called. If it returns a definitive result, the pipeline ends. - If the event does not deny item usage, `Item#useOn` is called. If it returns a definitive result, the pipeline ends. - `Item#use` is called. If it returns a definitive result, the pipeline ends. @@ -44,12 +44,12 @@ Generally, the different values mean the following: - `InteractionResult.SUCCESS` (or `InteractionResultHolder#success` where needed) should be used if the operation should be considered successful, and you want the arm to swing, but only on one side. Only use this if you want to return a different value on the other logical side for whatever reason. The pipeline will end. - `InteractionResult.CONSUME` (or `InteractionResultHolder#consume` where needed) should be used if the operation should be considered successful, but you do not want the arm to swing. The pipeline will end. - `InteractionResult.CONSUME_PARTIAL` is mostly identical to `InteractionResult.CONSUME`, the only difference is in its usage in [`Item#useOn`][itemuseon]. -- `InteractionResult.FAIL` (or `InteractionResultHolder#fail` where needed) should be used if the item functionality should be considered failed and no further interaction should be performed. The pipeline will end. This should only be used in `Item#useOn` and `Item#use`, all other implementations should use `InteractionResult.PASS` to allow item behavior to still be called. +- `InteractionResult.FAIL` (or `InteractionResultHolder#fail` where needed) should be used if the item functionality should be considered failed and no further interaction should be performed. The pipeline will end. This can be used everywhere, but it should be used with care outside of `Item#useOn` and `Item#use`. In many cases, using `InteractionResult.PASS` makes more sense. - `InteractionResult.PASS` (or `InteractionResultHolder#pass` where needed) should be used if the operation should be considered neither successful nor failed. The pipeline will continue. This is the default behavior (unless otherwise specified). Some methods have special behavior or requirements, which are explained in the below chapters. -`IForgeItem#onItemUseFirst` +`IItemExtension#onItemUseFirst` --------------------------- `InteractionResult#sidedSuccess` and `InteractionResult.CONSUME` don't have an effect here. Only `InteractionResult.SUCCESS`, `InteractionResult.FAIL` or `InteractionResult.PASS` should be used here. From 723dfe29a2cb723b4231250f666647dba695c794 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 <52419336+IchHabeHunger54@users.noreply.github.com> Date: Wed, 22 Nov 2023 15:38:05 +0100 Subject: [PATCH 23/27] Update docs/blocks/states.md Co-authored-by: Dennis C --- docs/blocks/states.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blocks/states.md b/docs/blocks/states.md index c044ce9ac..c0829286e 100644 --- a/docs/blocks/states.md +++ b/docs/blocks/states.md @@ -79,7 +79,7 @@ public class EndPortalFrameBlock extends Block { public static final DirectionProperty FACING = BlockStateProperties.FACING; public static final BooleanProperty EYE = BlockStateProperties.EYE; - public LeverBlock(BlockBehaviour.Properties pProperties) { + public EndPortalFrameBlock(BlockBehaviour.Properties pProperties) { super(pProperties); // stateDefinition.any() returns a random BlockState from an internal set, // we don't care because we're setting all values ourselves anyway From 03822eb2bd082efcc116b98be87d7c27d80bed14 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Wed, 22 Nov 2023 21:19:12 +0100 Subject: [PATCH 24/27] adjust to the new registry system --- docs/blocks/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index c82c76ab2..ef2f8f51d 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -11,8 +11,8 @@ Before we get started, it is important to understand that there is only ever one Due to this, a block should only ever be instantiated once, and that is during registration. Once the block is registered, you can then use the registered reference as needed. Consider this example (see the [Registration][registration] page if you do not know what you are looking at): ```java -//BLOCKS is a DeferredRegister -public static final RegistryObject MY_BLOCK = BLOCKS.register("my_block", () -> new Block(...)); +//BLOCKS is a DeferredRegister.Blocks +public static final Supplier MY_BLOCK = BLOCKS.register("my_block", () -> new Block(...)); ``` After registering the block, all references to the new `my_block` should use this constant. For example, if you want to check if the block at a given position is `my_block`, the code for that would look something like this: @@ -54,7 +54,7 @@ For simple blocks which need no special functionality (think cobblestone, wooden So for example, a simple implementation would look something like this: ```java -public static final RegistryObject MY_BETTER_BLOCK = BLOCKS.register( + public static final Supplier MY_BETTER_BLOCK = BLOCKS.register( "my_better_block", () -> new Block(BlockBehaviour.Properties.of() //highlight-start From 4c1ae304b685d8a0ec058c66f2ee2b665b4f7673 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 Date: Wed, 22 Nov 2023 21:20:57 +0100 Subject: [PATCH 25/27] simplify block breaking a bit --- docs/blocks/index.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index ef2f8f51d..85ad1ba7d 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -107,12 +107,11 @@ Block placement logic is called from `BlockItem#useOn` (or some subclass's imple ### Breaking a Block -Breaking a block is a bit more complex, as it requires time. The process can be roughly divided into four stages: "initiating", "mining", "actually breaking" and "finishing". +Breaking a block is a bit more complex, as it requires time. The process can be roughly divided into three stages: "initiating", "mining" and "actually breaking". - When the left mouse button is clicked, the "initiating" stage is entered. - Now, the left mouse button needs to be held down, entering the "mining" stage. **This stage's methods are called every tick.** - If the "continuing" stage is not interrupted (by releasing the left mouse button) and the block is broken, the "actually breaking" stage is entered. -- Under all circumstances, no matter if the block was actually broken or not, the "finishing" stage is entered. Or for those who prefer pseudocode: @@ -126,7 +125,6 @@ while (leftClickIsBeingHeld()) { break; } } -finishingStage(); ``` The following subsections further break down these stages into actual method calls. @@ -143,8 +141,8 @@ The following subsections further break down these stages into actual method cal #### The "Mining" Stage - `PlayerInteractEvent.LeftClickBlock` is fired. If the event is canceled, the pipeline moves to the "finishing" stage. - - Note that when the event is canceled on the client, no packets are sent to the server and thus no logic runs on the server. - - However, canceling this event on the server will still cause client code to run, which can lead to desyncs! + - Note that when the event is canceled on the client, no packets are sent to the server and thus no logic runs on the server. + - However, canceling this event on the server will still cause client code to run, which can lead to desyncs! - `Block#getDestroyProgress` is called and added to the internal destroy progress counter. - `Block#getDestroyProgress` returns a float value between 0 and 1, representing how much the destroy progress counter should be increased every tick. - The progress overlay (cracking texture) is updated accordingly. @@ -163,10 +161,6 @@ The following subsections further break down these stages into actual method cal - Server-only: `IBlockExtension#getExpDrop` is called. - Server-only: `Block#popExperience` is called with the result of the previous `IBlockExtension#getExpDrop` call, if that call returned a value greater than 0. -#### The "Finishing" Stage - -- The internal destroy progress counter is reset. - ### Ticking Ticking is a mechanism that updates (ticks) parts of the game every 1 / 20 seconds, or 50 milliseconds ("one tick"). Blocks provide different ticking methods that are called in different ways. From 6e6d97320b3964a0456c1a00b40e92cc4e8fca5a Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 <52419336+IchHabeHunger54@users.noreply.github.com> Date: Wed, 22 Nov 2023 21:41:36 +0100 Subject: [PATCH 26/27] Update docs/blocks/index.md Co-authored-by: Dennis C --- docs/blocks/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index 85ad1ba7d..c3b1d6c56 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -54,7 +54,7 @@ For simple blocks which need no special functionality (think cobblestone, wooden So for example, a simple implementation would look something like this: ```java - public static final Supplier MY_BETTER_BLOCK = BLOCKS.register( + public static final DeferredBlock MY_BETTER_BLOCK = BLOCKS.register( "my_better_block", () -> new Block(BlockBehaviour.Properties.of() //highlight-start From a8b4c53e22a511c2a491b4abfbd71d7b63aeb385 Mon Sep 17 00:00:00 2001 From: IchHabeHunger54 <52419336+IchHabeHunger54@users.noreply.github.com> Date: Fri, 24 Nov 2023 12:17:19 +0100 Subject: [PATCH 27/27] Update docs/blocks/index.md Co-authored-by: Dennis C --- docs/blocks/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blocks/index.md b/docs/blocks/index.md index c3b1d6c56..09567c52f 100644 --- a/docs/blocks/index.md +++ b/docs/blocks/index.md @@ -12,7 +12,7 @@ Due to this, a block should only ever be instantiated once, and that is during r ```java //BLOCKS is a DeferredRegister.Blocks -public static final Supplier MY_BLOCK = BLOCKS.register("my_block", () -> new Block(...)); +public static final DeferredBlock MY_BLOCK = BLOCKS.register("my_block", () -> new Block(...)); ``` After registering the block, all references to the new `my_block` should use this constant. For example, if you want to check if the block at a given position is `my_block`, the code for that would look something like this: