Skip to content

Commit

Permalink
docs: add advanced/block-and-item-id.md
Browse files Browse the repository at this point in the history
  • Loading branch information
smartcmd committed Jan 26, 2025
1 parent 116e794 commit 403af37
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 39 deletions.
52 changes: 13 additions & 39 deletions api/src/main/java/org/allaymc/api/utils/BlockAndItemIdMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,27 @@
import org.allaymc.api.item.data.ItemId;

/**
* TODO: translate to English and move it to docs site
*
* <br>
* 一个用于描述方块和物品字符串Id之间映射关系的工具类 <br>
* Id一直是mc中比较复杂的一部分,我们将所有相关逻辑都放到这里,方便阅读也方便后续维护 <br>
* <br>
* 所有的方块必将有一个对应的硬性方块物品,这里我们称之为“硬性方块物品”。但是并不是所有的物品都有对应的方块。 <br>
* 硬性方块物品的贴图只能是方块的渲染图。为了解决这个问题,原版还为某些方块注册了额外的方块物品,例如:蛋糕,炼药锅,草,海带,床,甘蔗(注意甘蔗比较特殊,后面讲)等等<br>
* 我们将这些额外注册的方块物品称为“实际方块物品”。<br>
* 在一个方块只有单独对应的方块物品时,“实际方块物品”就等于“硬性方块物品” <br>
* 原版方块&物品注册顺序:先注册物品,再注册方块(注册方块同时会注册方块的硬性方块物品,物品的id通常与方块相同,但有特例)。 <br>
* <br>
* 实际方块物品在物品注册阶段注册,先于方块。通常其id与对应的方块相同,例如蛋糕的实际方块物品id就是"minecraft:cake"。这时蛋糕方块还未注册<br>
* 在注册蛋糕方块的时候,同时还要注册一个蛋糕方块的硬性方块物品,但是"minecraft:cake"这个id已经被先前注册的物品占了<br>
* 原版在这种情况下就会在"cake"前加个"item."前缀,也就是"minecraft:item.cake" <br>
* 原版具有"item."前缀的物品有几十个 <br>
* <br>
* 特例:甘蔗 <br>
* 甘蔗是唯一不遵循上诉规则的物品,我们认为这是历史遗留问题 <br>
* 甘蔗的方块-硬性方块物品配对为"minecraft:reeds" <-> "minecraft:item.reeds" <br>
* 而方块-实际方块物品配对则为"minecraft:reeds" <-> "minecraft:sugar_cane" <br>
* 可以看到甘蔗的实际方块物品id并不与其方块id相同 <br>
* <br>
* 为了统一命名,减少混乱。在allay中,我们保证注册的方块物品的硬性方块物品id在没有id冲突的情况下与方块id相同 <br>
* 若你想为你的方块注册额外的方块物品,请确保其id与对应方块id一致。稍后在注册一个方块时,若allay发现已有一个与方块id相同的物品,将把其作为实际使用的方块物品(也就是方法BlockType.getItemType()的返回值)<br>
* 但是即便如此,硬性方块物品仍然会被注册。和原版相同,我们将加上前缀"item."
* <br>
* 请注意,对于原版方块物品,若其meta(特殊值)不等于0,则不同特殊值的物品还有可能映射到一个方块类型的不同的方块状态上 <br>
* 具体点说,此类物品特殊值是由对应方块状态的各个方块属性序列化后全填充二进制位得到的。我们不推荐继续使用特殊值,这里也不会细讲具体逻辑<br>
* 此类映射关系由类org.allaymc.server.util.VanillaItemMetaBlockStateBiMap维护<br>
* A class that handle the mapping relation between block and item id.
* See more details in `block-and-item-id.md`.
*
* @author daoge_cmd
*/
public final class BlockAndItemIdMapper {

// Naming conflict prefix
/**
* Naming conflict prefix
*/
public static final String NAMING_CONFLICT_PATH_PREFIX = "item.";

/**
* 需要调用方保证传入的itemId是方块物品,且方块与方块物品的命名规则合法。否则不存在id为返回值的方块
* Try to get the block id of an item.
*
* @param itemId 物品id
* @param itemId the id of the item.
*
* @return 可能的方块id
* @return the block id, or {@code null} if the item does not have correspond block (`pure item`).
*/
public static Identifier itemIdToPossibleBlockId(Identifier itemId) {
// 特例:甘蔗
// Special case: sugar cane
if (itemId.equals(ItemId.SUGAR_CANE.getIdentifier())) {
return BlockId.REEDS.getIdentifier();
}
Expand All @@ -62,14 +36,14 @@ public static Identifier itemIdToPossibleBlockId(Identifier itemId) {
}

/**
* 我们无法仅凭方块id判断其是否有额外的方块物品,不过我们可以推断出其实际方块物品
* Get the `actual block item` id of a block.
*
* @param blockId 方块id
* @param blockId the id of the block.
*
* @return 实际方块物品id
* @return the `actual block item` id.
*/
public static Identifier blockIdToActualBlockItemId(Identifier blockId) {
// 特例:甘蔗
// Special case: sugar cane
if (blockId.equals(BlockId.REEDS.getIdentifier())) {
return ItemId.SUGAR_CANE.getIdentifier();
}
Expand Down
53 changes: 53 additions & 0 deletions docs/advanced/block-and-item-id.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
comments: true
---

# Block and Item Id

This page will explain the id system of block and item.

## Overview

In Minecraft: Bedrock Edition, all blocks must have a correspond `hard block item`. But not every item have a correspond block.
If an item does not have a correspond block, then we call it `pure item`. The texture of `hard block item` is decided by the block's
texture and cannot be changed. To solve this problem, the vanilla also registered extra block item for some blocks (e.g. cake,
cauldron, grass, kelp, bed, sugar cane, etc.). We called these extra block items `actual block item`.

When a block only have one correspond block item, `hard block item` is equal to `actual block item`. Most of the blocks in vanilla
are like this.

## How Blocks & Items are Registered and How the Order Affect the Id

The register order of blocks and items in vanilla:

1. Register all `pure item` and `actual block item`.
2. Register all blocks, and try to register `hard block item` with the same id of block for each block, and there are two cases:
1. There is no `actual block item` that already registered with the same id, which means that this block only have one correspond block item.
We can say that the `hard block item` is equal to the `actual block item` of this block.
2. There is an `actual block item` that already registered with the same id, which means that the `hard block item` and `actual block item`
of this block is different. **However, the `hard block item` will still be registered, and to solve the conflict, a perfix `item.` will
be added to the path of the id**.

Here, we will take cake (whose `hard block item` is different from its `actual block item`) as an example:

1. Register the `actual block item`: `minecraft:cake`.
2. Register the block: `minecarft:cake`.
3. Try to register the `hard block item` with the same id of block: `minecraft:cake`.
But there is already an `actual block item` with the same id, so the `hard block item` will be registered with the id `minecraft:item.cake`.

## Special Cases

Normally, for a block, you can find an item of the same block ID. But there are special cases here (for historical reasons):

| Block Id | Actual Block Item Id | Hard Block Item Id |
|-----------------|------------------------------------------|----------------------|
| minecraft:reeds | ~~minecraft:reeds~~ minecraft:sugar_cane | minecraft:item.reeds |

## How Allay Handles Block and Item Id

To unify naming and reduce confusion. In Allay, we ensure that the `hard block item`'s id of the registered block is the same as the block's id
without an id conflict. If you want to register extra block item for your block, please make sure that it has the same id of the blcok you want
to register extra block item for. Later when registering the block, Allay will consider the item you registered as the `actual block item`, and
register the `hard block item` with a `item.` prefix.

The return value of `BlockType#getItemType()` will be the `actual block item` instead of the `hard block item` if the block has extra block item.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ nav:

- Advanced:
- Use Color Codes: advanced/use-color-codes.md
- Block and Item Id: advanced/block-and-item-id.md

- Development:
- Update to The Next Protocol Version: development/update-to-the-next-protocol-version.md
Expand Down

0 comments on commit 403af37

Please sign in to comment.