Skip to content

✨ feat: add custom hitboxes and rework related modules #465

New issue

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

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

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 51 additions & 6 deletions data/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,21 @@
"runtime"
],
"features": [
{
"id": "#bs.hitbox:bake_entity",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/hitbox.html#bake-entity",
"authors": [
"Aksiome"
],
"created": {
"date": "2025/05/18",
"minecraft_version": "1.21.5"
},
"updated": {
"date": "2025/05/18",
"minecraft_version": "1.21.5"
}
},
{
"id": "#bs.hitbox:can_pass_through",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/hitbox.html#blocks",
Expand Down Expand Up @@ -1013,7 +1028,7 @@
},
{
"id": "#bs.hitbox:intangible",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/hitbox.html#entities",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/hitbox.html#blocks",
"authors": [
"Aksiome"
],
Expand All @@ -1022,13 +1037,13 @@
"minecraft_version": "1.21"
},
"updated": {
"date": "2024/09/28",
"minecraft_version": "1.21"
"date": "2025/03/10",
"minecraft_version": "1.21.4"
}
},
{
"id": "#bs.hitbox:intangible",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/hitbox.html#blocks",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/hitbox.html#entities",
"authors": [
"Aksiome"
],
Expand All @@ -1037,8 +1052,8 @@
"minecraft_version": "1.21"
},
"updated": {
"date": "2025/03/10",
"minecraft_version": "1.21.4"
"date": "2024/09/28",
"minecraft_version": "1.21"
}
},
{
Expand Down Expand Up @@ -1190,6 +1205,36 @@
"date": "2024/10/28",
"minecraft_version": "1.21.2"
}
},
{
"id": "#bs.hitbox:reset_entity",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/hitbox.html#reset-entity",
"authors": [
"Aksiome"
],
"created": {
"date": "2025/05/18",
"minecraft_version": "1.21.5"
},
"updated": {
"date": "2025/05/18",
"minecraft_version": "1.21.5"
}
},
{
"id": "#bs.hitbox:set_entity",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/hitbox.html#set-entity",
"authors": [
"Aksiome"
],
"created": {
"date": "2025/05/18",
"minecraft_version": "1.21.5"
},
"updated": {
"date": "2025/05/18",
"minecraft_version": "1.21.5"
}
}
]
},
Expand Down
182 changes: 176 additions & 6 deletions docs/modules/hitbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,37 @@ You can find below all functions available in this module.

---

### Bake Entity

```{function} #bs.hitbox:bake_entity

Bake an entity’s hitbox to improve performance when its size never changes. If the entity has passengers, they are also baked, and the base entity's hitbox is expanded to include the full bounding box of the entire stack.

:Inputs:
**Execution `as <entities>`**: The entity or entities whose hitboxes should be baked.

:Outputs:
**State**: The entity's hitbox is saved in a baked state for later use.
```

```{warning}
Only use baked hitboxes when you are sure the entity’s size will not change, for example: no growth (babies), no scaling, no new passengers, and no equipment that could affect size.

If the hitbox changes after baking, **it may lead to incorrect collisions or broken logic**.
```

```{admonition} What is a Baked Hitbox?
:class: dropdown

Baking captures a snapshot of the entity's hitbox at a specific moment. It does not update after that. If the entity has passengers, the baked result includes a bounding box that encapsulates both the base entity and all passengers.

See [Hitbox Types](#types) for full details on block and entity hitboxes.
```

> **Credits**: Aksiome

---

### Get

:::::{tab-set}
Expand All @@ -42,10 +73,12 @@ Get the hitbox of a block as a shape, represented by a list of boxes coordinates
:::
```

```{admonition} Collision / Interaction Shape
:class: info
```{admonition} Collision or Interaction Shape?
:class: dropdown
- **Collision Shape**: Defines the physical boundaries of a block that entities cannot pass through. It determines where an entity will stop when moving towards the block.
- **Interaction Shape**: Defines the area where the player can interact with or break the block. This includes actions such as right-clicking to open a GUI (e.g., chests, furnaces) or mining the block. Some blocks have an interaction shape but no collision, such as crops or scaffolding.

See [Hitbox Types](#types) for full details on block and entity hitboxes.
```

*Example: Get the hitbox of stairs:*
Expand All @@ -70,14 +103,17 @@ Get the width and height of an entity.
**Storage `bs:out hitbox`**:
:::{treeview}
- {nbt}`compound` Entity hitbox data
- {nbt}`double` **height**: Height of the entity.
- {nbt}`double` **width**: Width of the entity.
- {nbt}`double` **width**: Width of the entity (X axis).
- {nbt}`double` **height**: Height of the entity (Y axis).
- {nbt}`double` **depth**: Depth of the entity (Z axis).
- {nbt}`double` **scale**: Scaling of the hitbox.
:::
```

```{important}
Static entities, such as paintings and item frames, do not provide height and width information. Instead, they return a shape similar to blocks in `bs:out hitbox.shape`.
```{note}
For most entities without a custom hitbox, `depth` is equal to `width`.
However, static entities like paintings and item frames use shaped hitboxes and may return different dimensions.
Their full shape is also available in `bs:out hitbox.shape`, in a format similar to block shapes.
```

*Example: Get the hitbox of an armor stand:*
Expand Down Expand Up @@ -284,6 +320,65 @@ execute summon minecraft:cow if function #bs.hitbox:is_in_entity run say Oh no..

---

### Reset Entity

```{function} #bs.hitbox:reset_entity

Reset an entity's hitbox to its default **dynamic** form, removing any previously applied **baked** or **custom** hitbox.

:Inputs:
**Execution `as <entities>`**: The entity or entities whose hitboxes should be reset.

:Outputs:
**State**: The entity’s hitbox is now dynamic again and will automatically update with scaling, growth, or other changes.
```

> **Credits**: Aksiome

---

### Set Entity

```{function} #bs.hitbox:set_entity

Define a custom hitbox for an entity with full control over its dimensions. This allows setting a hitbox not constrained by Minecraft’s built-in width/height system and can be used on entities that normally have no hitbox.

:Inputs:
**Execution `as <entities>`**: The entity or entities whose hitboxes should be set with custom dimensions.

**Function macro**:
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`compound` **with**: Hitbox data.
- {nbt}`double` **width**: The total horizontal size along the X axis.
- {nbt}`double` **height**: The total vertical size along the Y axis.
- {nbt}`double` **depth**: The total size along the Z axis. Defaults to the same value as **width** if not provided.
- {nbt}`bool` **centered**: Whether the hitbox should be vertically centered on the Y axis. Defaults to `false`, meaning the hitbox starts at the entity's feet (like in vanilla).
:::
:Outputs:
**State**: The entity now has a custom axis-aligned bounding box (AABB) hitbox.
```

```{warning}
Custom hitboxes come with a **small performance cost**. Use them when you need precise control over shape and position, but avoid using too many of them in the same area.
```

```{admonition} What is a Custom Hitbox?
:class: dropdown

A custom hitbox lets you override Minecraft's default hitbox system and define your own shape using width, height, and depth. Unlike dynamic or baked hitboxes, custom hitboxes:

- Can be **freely shaped**, including along the Z axis (depth).
- Are not tied to Minecraft's internal collision model.
- Work on entities **without a native hitbox**, such as display entities.

See [Hitbox Types](#types) for full details on block and entity hitboxes.
```

> **Credits**: Aksiome

---

## 🏷️ Tags

You can find below below all tags available in this module.
Expand Down Expand Up @@ -357,5 +452,80 @@ Identifies if the entity has a rectangular hitbox size.

---

(types)=
## 🎓 Hitbox Types

Bookshelf provides two block and three entity hitbox types, each suited to different use cases. Understanding the differences helps you choose the right one.

---

### Blocks

::::{tab-set}
:::{tab-item} 🧊 collision

The `collision` shape defines the physical boundaries of a block that entities cannot pass through. It determines where an entity will stop when moving towards the block:

- Matches the block’s solid parts and prevents entities from moving through.
- Can change dynamically depending on block state (e.g., a fence gate’s collision shape differs when open vs closed).

➔ Returned by [#bs.hitbox:get_block](#get)

:::
:::{tab-item} 🖱 interaction

The `interaction` shape defines the area where players can interact with or break the block:

- Specifies the zone where right-clicks, mining, or other interactions register.
- Can differ from the collision shape, for example, fence gates keep the same interaction zone whether open or closed.

➔ Returned by [#bs.hitbox:get_block](#get)

:::
::::

---

### Entities

::::{tab-set}
:::{tab-item} 🔄 dynamic

This is the native Minecraft hitbox, which updates automatically:

- Adjusts in real time with entity changes like scaling, baby growth, equipment, or new passengers.
- No setup required, this is the default behavior.
- Use when the entity’s shape is expected to change.

➔ Restored using [#bs.hitbox:reset_entity](#reset-entity)

:::
:::{tab-item} ❄️ baked

A snapshot of the entity’s hitbox at a specific moment:

- Improves performance when the entity’s size will never change.
- Includes the base entity and all passengers in one combined box.
- Does not update dynamically, collisions may break if the entity changes later.

➔ Set using [#bs.hitbox:bake_entity](#bake-entity)

:::
:::{tab-item} 🛠️ custom

A fully user-defined hitbox:

- Set exact `width`, `height`, and optional `depth`.
- Works on entities with no native hitbox (e.g. display entities).
- Independent from Minecraft’s internal hitbox system.
- Slight performance cost, avoid overuse in the same area.

➔ Set using [#bs.hitbox:set_entity](#set-entity)

:::
::::

---

```{include} ../_templates/comments.md
```
21 changes: 10 additions & 11 deletions docs/modules/move.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,10 @@ Teleport an entity by its velocity scores while handling collisions.
- {nbt}`compound` Arguments
- {nbt}`number` **scale**: Scalar applied to the output.
- {nbt}`compound` **with**: Collision settings.
- {nbt}`bool` **blocks**: Whether the entity should collide with blocks (default: true).
- {nbt}`bool` {nbt}`string` **entities**: Whether the entity should collide with entities (default: false). Can also be a tag that entities must have.
- {nbt}`string` **hitbox_shape**: Hitbox type: `interaction` or `collision` (default: `collision`).
- {nbt}`bool` {nbt}`string` **blocks**: Whether the entity should collide with blocks (default: true). Can be a block hitbox type (`interaction` or `collision`). `true` defaults to `collision`.
- {nbt}`bool` {nbt}`string` **entities**: Whether the entity should collide with entities (default: false). Can be an entity tag. For performance, tagging entities to detect is recommended.
- {nbt}`string` **ignored_blocks**: Blocks to ignore (default: `#bs.hitbox:can_pass_through`).
- {nbt}`string` **ignored_entities**: Entities to ignore (default: `#bs.hitbox:intangible`).
- {nbt}`string` **ignored_entities**: Entities to ignore (default: `#bs.hitbox:intangible`). Does not apply to entities with custom hitboxes.
- {nbt}`string` **on_collision**: Command to run when a collision occurs, used to resolve the collision (default: `function #bs.move:callback/bounce`).
:::

Expand Down Expand Up @@ -87,11 +86,10 @@ Teleport an entity by its velocity scores, using the local reference frame, whil
- {nbt}`compound` Arguments
- {nbt}`number` **scale**: Scalar applied to the output.
- {nbt}`compound` **with**: Collision settings.
- {nbt}`bool` **blocks**: Whether the entity should collide with blocks (default: true).
- {nbt}`bool` {nbt}`string` **entities**: Whether the entity should collide with entities (default: false). Can also be a tag that entities must have.
- {nbt}`string` **hitbox_shape**: Hitbox type: `interaction` or `collision` (default: `collision`).
- {nbt}`bool` {nbt}`string` **blocks**: Whether the entity should collide with blocks (default: true). Can be a block hitbox type (`interaction` or `collision`). `true` defaults to `collision`.
- {nbt}`bool` {nbt}`string` **entities**: Whether the entity should collide with entities (default: false). Can be an entity tag. For performance, tagging entities to detect is recommended.
- {nbt}`string` **ignored_blocks**: Blocks to ignore (default: `#bs.hitbox:can_pass_through`).
- {nbt}`string` **ignored_entities**: Entities to ignore (default: `#bs.hitbox:intangible`).
- {nbt}`string` **ignored_entities**: Entities to ignore (default: `#bs.hitbox:intangible`). Does not apply to entities with custom hitboxes.
- {nbt}`string` **on_collision**: Command to run when a collision occurs, used to resolve the collision (default: `function #bs.move:callback/bounce`).
:::

Expand All @@ -102,10 +100,11 @@ Teleport an entity by its velocity scores, using the local reference frame, whil
::::
:::::

```{admonition} Collision / Interaction Shape
```{admonition} Hitbox Types
:class: info
- **Collision Shape**: Defines the physical boundaries of a block that entities cannot pass through. It determines where an entity will stop when moving towards the block.
- **Interaction Shape**: Defines the area where the player can interact with or break the block. This includes actions such as right-clicking to open a GUI (e.g., chests, furnaces) or mining the block. Some blocks have an interaction shape but no collision, such as crops or scaffolding.
Bookshelf supports multiple hitbox types for precise control. Blocks can use either `interaction` or `collision` hitboxes. Entities support three types: `dynamic`, `baked`, and `custom`.

See [Hitbox Types](hitbox.md#types) for full details.
```

*Example: Move a cube (block_display) by its velocity scores (uses an interaction as the hitbox):*
Expand Down
14 changes: 7 additions & 7 deletions docs/modules/raycast.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,12 @@ Cast a ray from the execution position and check if it hits something.
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`compound` **with**: Ray input data.
- {nbt}`bool` **blocks**: Whether the ray should stop on blocks (default: true).
- {nbt}`bool` {nbt}`string` **entities**: Whether the ray should stop on entities (default: false). Can also be a required entity tag.
- {nbt}`bool` {nbt}`string` **blocks**: Whether the ray stops on blocks (default: true). Can be a block hitbox type (`interaction` or `collision`). `true` defaults to `interaction`.
- {nbt}`bool` {nbt}`string` **entities**: Whether the ray stops on entities (default: false). Can be an entity tag. For performance, tagging entities to detect is recommended.
- {nbt}`int` **piercing**: Number of blocks or entities the ray can pass through (default: 0).
- {nbt}`number` **max_distance**: Maximum ray travel distance (default: 16.0).
- {nbt}`string` **hitbox_shape**: Hitbox type: `interaction` or `collision` (default: `interaction`).
- {nbt}`string` **ignored_blocks**: Blocks to ignore (default: `#bs.hitbox:intangible`).
- {nbt}`string` **ignored_entities**: Entities to ignore (default: `#bs.hitbox:intangible`).
- {nbt}`string` **ignored_entities**: Entities to ignore (default: `#bs.hitbox:intangible`). Does not apply to entities with custom hitboxes.
- {nbt}`string` **on_hit_point**: Command to run at the exact point where the ray makes contact.
- {nbt}`string` **on_targeted_block**: Command to run at the block hit by the ray.
- {nbt}`string` **on_targeted_entity**: Command to run as and at the entity hit by the ray.
Expand Down Expand Up @@ -74,10 +73,11 @@ Cast a ray from the execution position and check if it hits something.
:::
```

```{admonition} Collision / Interaction Shape
```{admonition} Hitbox Types
:class: info
- **Collision Shape**: Defines the physical boundaries of a block that entities cannot pass through. It determines where an entity will stop when moving towards the block.
- **Interaction Shape**: Defines the area where the player can interact with or break the block. This includes actions such as right-clicking to open a GUI (e.g., chests, furnaces) or mining the block. Some blocks have an interaction shape but no collision, such as crops or scaffolding.
Bookshelf supports multiple hitbox types for precise control. Blocks can use either `interaction` or `collision` hitboxes. Entities support three types: `dynamic`, `baked`, and `custom`.

See [Hitbox Types](hitbox.md#types) for full details.
```

*Example: Cast a ray from your eyes and detect any collisions:*
Expand Down
Loading
Loading