Skip to content

✨ feat(bs.spline): add linear spline type #451

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

Merged
merged 2 commits into from
Jun 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions data/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3561,6 +3561,21 @@
"minecraft_version": "1.21.5"
}
},
{
"id": "#bs.spline:evaluate_linear",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/spline.html#evaluate",
"authors": [
"Aksiome"
],
"created": {
"date": "2025/05/14",
"minecraft_version": "1.21.5"
},
"updated": {
"date": "2025/05/14",
"minecraft_version": "1.21.5"
}
},
{
"id": "#bs.spline:sample_bezier",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/spline.html#sample",
Expand Down Expand Up @@ -3621,6 +3636,21 @@
"minecraft_version": "1.21.5"
}
},
{
"id": "#bs.spline:sample_linear",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/spline.html#sample",
"authors": [
"Aksiome"
],
"created": {
"date": "2025/05/14",
"minecraft_version": "1.21.5"
},
"updated": {
"date": "2025/05/14",
"minecraft_version": "1.21.5"
}
},
{
"id": "#bs.spline:stream_bezier",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/spline.html#stream",
Expand Down Expand Up @@ -3680,6 +3710,21 @@
"date": "2025/04/21",
"minecraft_version": "1.21.5"
}
},
{
"id": "#bs.spline:stream_linear",
"documentation": "https://docs.mcbookshelf.dev/en/latest/modules/spline.html#stream",
"authors": [
"Aksiome"
],
"created": {
"date": "2025/05/14",
"minecraft_version": "1.21.5"
},
"updated": {
"date": "2025/05/14",
"minecraft_version": "1.21.5"
}
}
]
},
Expand Down
10 changes: 8 additions & 2 deletions docs/changelog/v3.1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@
> *[Update Description]*


### `🔬 bs.dump`

- <abbr title="Bug Fix">🐛</abbr> **[#441](https://github.com/mcbookshelf/bookshelf/issues/441)** - Fixed `#bs.dump:var` incorrectly appending `undefined` to output.


### `🔦 bs.raycast`

- <abbr title="New Feature">✨</abbr> **[#445](https://github.com/mcbookshelf/bookshelf/issues/445)** - `#bs.raycast:run` now computes all lambda data before invoking callbacks.

### `🔬 bs.dump`

- <abbr title="Bug Fix">🐛</abbr> **[#441](https://github.com/mcbookshelf/bookshelf/issues/441)** - Fixed `#bs.dump:var` incorrectly appending `undefined` to output.
### `🧣 bs.spline`

- <abbr title="New Feature">✨</abbr> **[#417](https://github.com/mcbookshelf/bookshelf/issues/417)** - Added full support for **linear splines**.
103 changes: 91 additions & 12 deletions docs/modules/spline.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,33 @@ function #bs.spline:evaluate_hermite
data get storage bs:out spline.evaluate_hermite
```

::::
::::{tab-item} Linear

```{function} #bs.spline:evaluate_linear

Evaluate a linear spline, which connects each pair of consecutive points with a straight segment. There is no curvature; the interpolation is piecewise linear.

:Inputs:
**Storage `bs:in spline.evaluate_linear`**:
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Each pair of consecutive points defines one linear segment.
- {nbt}`double` **time**: A normalized position between 0 and the number of segments. Each integer step moves to the next segment, and the fractional part represents interpolation within that segment.
:::

:Outputs:
**Storage `bs:out spline.evaluate_linear`**: {nbt}`list` The interpolated point (1D, 2D, or 3D) on the spline at the given time.
```

*Example: Evaluate the midpoint between two positions in 2D space:*

```mcfunction
data modify storage bs:in spline.evaluate_linear set value {points:[[0,0],[4,2],[6,5]],time:0.5}
function #bs.spline:evaluate_linear
data get storage bs:out spline.evaluate_linear
```

::::
:::::

Expand All @@ -164,7 +191,7 @@ Sample a Bézier spline composed of one or more segments. Each segment is define
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Every group of 4 consecutive points defines one segment.
- {nbt}`double` **step**: The interval at which the curve is sampled. Smaller values generate more points.
- {nbt}`double` **step**: The interval at which the spline is sampled. Smaller values generate more points.
:::

:Outputs:
Expand All @@ -191,7 +218,7 @@ Sample a B-Spline composed of one or more segments. Each segment is defined by f
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Every group of 4 consecutive points defines one segment.
- {nbt}`double` **step**: The interval at which the curve is sampled. Smaller values generate more points.
- {nbt}`double` **step**: The interval at which the spline is sampled. Smaller values generate more points.
:::

:Outputs:
Expand All @@ -218,7 +245,7 @@ Sample a Catmull-Rom spline composed of one or more segments. Each segment is de
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Every group of 4 consecutive points defines one segment.
- {nbt}`double` **step**: The interval at which the curve is sampled. Smaller values generate more points.
- {nbt}`double` **step**: The interval at which the spline is sampled. Smaller values generate more points.
:::

:Outputs:
Expand All @@ -245,7 +272,7 @@ Sample a Hermite spline composed of one or more segments. Each segment is define
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Every group of 4 consecutive points defines one segment.
- {nbt}`double` **step**: The interval at which the curve is sampled. Smaller values generate more points.
- {nbt}`double` **step**: The interval at which the spline is sampled. Smaller values generate more points.
:::

:Outputs:
Expand All @@ -260,6 +287,33 @@ function #bs.spline:sample_hermite
data get storage bs:out spline.sample_hermite
```

::::
::::{tab-item} Linear

```{function} #bs.spline:sample_linear

Sample a linear spline, which connects each pair of consecutive points with a straight segment.

:Inputs:
**Storage `bs:in spline.sample_linear`**:
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Each pair of consecutive points defines one linear segment.
- {nbt}`double` **step**: The interval at which the spline is sampled. Smaller values generate more points.
:::

:Outputs:
**Storage `bs:out spline.sample_linear`**: {nbt}`list` The sampled points along the spline.
```

*Example: Sample evenly spaced points along a polyline in 2D space:*

```mcfunction
data modify storage bs:in spline.sample_linear set value {points:[[0,0],[4,2],[6,5]],step:0.25}
function #bs.spline:sample_linear
data get storage bs:out spline.sample_linear
```

::::
:::::

Expand All @@ -279,8 +333,8 @@ Stream a Bézier spline composed of one or more segments. Each segment is define
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Every group of 4 consecutive points defines one segment.
- {nbt}`double` **step**: The interval at which the curve is sampled. Smaller values generate more points.
- {nbt}`string` **run**: The command executed at each step of the curve sampling process. For each step, the following storage can be used:
- {nbt}`double` **step**: The interval at which the spline is sampled. Smaller values generate more points.
- {nbt}`string` **run**: The command executed at each step of the sampling process. For each step, the following storage can be used:
- **`bs:lambda spline.point`**: The evaluated point.
:::
```
Expand All @@ -304,8 +358,8 @@ Stream a B-Spline composed of one or more segments. Each segment is defined by f
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Every group of 4 consecutive points defines one segment.
- {nbt}`double` **step**: The interval at which the curve is sampled. Smaller values generate more points.
- {nbt}`string` **run**: The command executed at each step of the curve sampling process. For each step, the following storage can be used:
- {nbt}`double` **step**: The interval at which the spline is sampled. Smaller values generate more points.
- {nbt}`string` **run**: The command executed at each step of the sampling process. For each step, the following storage can be used:
- **`bs:lambda spline.point`**: The evaluated point.
:::
```
Expand All @@ -329,8 +383,8 @@ Stream a Catmull-Rom spline composed of one or more segments. Each segment is de
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Every group of 4 consecutive points defines one segment.
- {nbt}`double` **step**: The interval at which the curve is sampled. Smaller values generate more points.
- {nbt}`string` **run**: The command executed at each step of the curve sampling process. For each step, the following storage can be used:
- {nbt}`double` **step**: The interval at which the spline is sampled. Smaller values generate more points.
- {nbt}`string` **run**: The command executed at each step of the sampling process. For each step, the following storage can be used:
- **`bs:lambda spline.point`**: The evaluated point.
:::
```
Expand All @@ -354,8 +408,8 @@ Stream a Hermite spline composed of one or more segments. Each segment is define
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Every group of 4 consecutive points defines one segment.
- {nbt}`double` **step**: The interval at which the curve is sampled. Smaller values generate more points.
- {nbt}`string` **run**: The command executed at each step of the curve sampling process. For each step, the following storage can be used:
- {nbt}`double` **step**: The interval at which the spline is sampled. Smaller values generate more points.
- {nbt}`string` **run**: The command executed at each step of the sampling process. For each step, the following storage can be used:
- **`bs:lambda spline.point`**: The evaluated point.
:::
```
Expand All @@ -367,6 +421,31 @@ data modify storage bs:in spline.stream_hermite set value {points:[[0,0],[1,2],[
function #bs.spline:stream_hermite
```

::::
::::{tab-item} Linear

```{function} #bs.spline:stream_linear

Stream a linear spline composed of one or more segments. Each segment connects two consecutive control points with a straight line. This function processes each step over multiple ticks.

:Inputs:
**Storage `bs:in spline.stream_linear`**:
:::{treeview}
- {nbt}`compound` Arguments
- {nbt}`list` **points**: A list of coordinates (1D, 2D, or 3D). Every pair of consecutive points defines one linear segment.
- {nbt}`double` **step**: The interval at which the spline is sampled. Smaller values generate more points.
- {nbt}`string` **run**: The command executed at each step of the sampling process. For each step, the following storage can be used:
- **`bs:lambda spline.point`**: The evaluated point.
:::
```

*Example: Stream 10 points along a linear path in 2D space and execute a command at each step:*

```mcfunction
data modify storage bs:in spline.stream_linear set value {points:[[0,0],[1,2],[3,0]],step:0.1,run:'tellraw @a {"storage":"bs:lambda","nbt":"spline.point"}'}
function #bs.spline:stream_linear
```

::::
:::::

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ------------------------------------------------------------------------------------------------------------
# Copyright (c) 2025 Gunivers
#
# This file is part of the Bookshelf project (https://github.com/mcbookshelf/bookshelf).
#
# This source code is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Conditions:
# - You may use this file in compliance with the MPL v2.0
# - Any modifications must be documented and disclosed under the same license
#
# For more details, refer to the MPL v2.0.
# ------------------------------------------------------------------------------------------------------------

data modify storage bs:ctx _ set from storage bs:in spline.evaluate_linear
data modify storage bs:out spline.evaluate_linear set value []

execute store result score #s bs.ctx store result score #t bs.ctx run data get storage bs:ctx _.time 1000
scoreboard players operation #s bs.ctx /= 1000 bs.const
execute if score #s bs.ctx matches 1.. run function bs.spline:utils/linear/get_segment

execute store result score #m bs.ctx if data storage bs:ctx _.points[]
execute store result score #n bs.ctx if data storage bs:ctx _.points[][2]
execute if score #n bs.ctx = #m bs.ctx run return run function bs.spline:evaluate/evaluate_3d {type:"linear"}
execute store result score #n bs.ctx if data storage bs:ctx _.points[][1]
execute if score #n bs.ctx = #m bs.ctx run return run function bs.spline:evaluate/evaluate_2d {type:"linear"}
execute store result score #n bs.ctx if data storage bs:ctx _.points[][0]
execute if score #n bs.ctx = #m bs.ctx run return run function bs.spline:evaluate/evaluate_1d {type:"linear"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ------------------------------------------------------------------------------------------------------------
# Copyright (c) 2025 Gunivers
#
# This file is part of the Bookshelf project (https://github.com/mcbookshelf/bookshelf).
#
# This source code is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Conditions:
# - You may use this file in compliance with the MPL v2.0
# - Any modifications must be documented and disclosed under the same license
#
# For more details, refer to the MPL v2.0.
# ------------------------------------------------------------------------------------------------------------

data modify storage bs:ctx _ set from storage bs:in spline.sample_linear
data modify storage bs:out spline.sample_linear set value []

scoreboard players set #t bs.ctx 1000
execute store result score #s bs.ctx run data get storage bs:ctx _.step 1000
scoreboard players operation #t bs.ctx -= #s bs.ctx

execute store result score #m bs.ctx if data storage bs:ctx _.points[]
execute store result score #n bs.ctx if data storage bs:ctx _.points[][2]
execute if score #n bs.ctx = #m bs.ctx run return run function bs.spline:sample/sample_3d {type:"linear"}
execute store result score #n bs.ctx if data storage bs:ctx _.points[][1]
execute if score #n bs.ctx = #m bs.ctx run return run function bs.spline:sample/sample_2d {type:"linear"}
execute store result score #n bs.ctx if data storage bs:ctx _.points[][0]
execute if score #n bs.ctx = #m bs.ctx run return run function bs.spline:sample/sample_1d {type:"linear"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# ------------------------------------------------------------------------------------------------------------
# Copyright (c) 2025 Gunivers
#
# This file is part of the Bookshelf project (https://github.com/mcbookshelf/bookshelf).
#
# This source code is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Conditions:
# - You may use this file in compliance with the MPL v2.0
# - Any modifications must be documented and disclosed under the same license
#
# For more details, refer to the MPL v2.0.
# ------------------------------------------------------------------------------------------------------------

data modify storage bs:ctx _ set from storage bs:in spline.stream_linear
data modify storage bs:ctx _.type set value "linear"

scoreboard players set #t bs.ctx 1000
execute store result score #s bs.ctx run data get storage bs:ctx _.step 1000
scoreboard players operation #t bs.ctx -= #s bs.ctx

execute store result score #m bs.ctx if data storage bs:ctx _.points[]
execute store result score #n bs.ctx if data storage bs:ctx _.points[][2]
execute if score #n bs.ctx = #m bs.ctx run data modify storage bs:ctx _.coeffs set value [0,0,0,0]
execute if score #n bs.ctx = #m bs.ctx run return run function bs.spline:stream/stream_3d with storage bs:ctx _
execute store result score #n bs.ctx if data storage bs:ctx _.points[][1]
execute if score #n bs.ctx = #m bs.ctx run data modify storage bs:ctx _.coeffs set value [0,0,0,0,0,0,0,0]
execute if score #n bs.ctx = #m bs.ctx run return run function bs.spline:stream/stream_2d with storage bs:ctx _
execute store result score #n bs.ctx if data storage bs:ctx _.points[][0]
execute if score #n bs.ctx = #m bs.ctx run data modify storage bs:ctx _.coeffs set value [0,0,0,0,0,0,0,0,0,0,0,0]
execute if score #n bs.ctx = #m bs.ctx run return run function bs.spline:stream/stream_1d with storage bs:ctx _
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
# ------------------------------------------------------------------------------------------------------------

data modify storage bs:lambda spline.point set value [0d, 0d]
execute store result score #x bs.ctx store result score #y bs.ctx run scoreboard players operation #t bs.ctx %= 1000 bs.const
execute store result score #x bs.ctx \
store result score #y bs.ctx \
run scoreboard players operation #t bs.ctx %= 1000 bs.const

execute store result score #a bs.ctx run data get storage bs:ctx _.points[0][0] 1000
execute store result score #b bs.ctx run data get storage bs:ctx _.points[1][0] 1000
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
# ------------------------------------------------------------------------------------------------------------

data modify storage bs:lambda spline.point set value [0d, 0d, 0d]
execute store result score #x bs.ctx store result score #y bs.ctx store result score #z bs.ctx run scoreboard players operation #t bs.ctx %= 1000 bs.const
execute store result score #x bs.ctx \
store result score #y bs.ctx \
store result score #z bs.ctx \
run scoreboard players operation #t bs.ctx %= 1000 bs.const

execute store result score #a bs.ctx run data get storage bs:ctx _.points[0][0] 1000
execute store result score #b bs.ctx run data get storage bs:ctx _.points[1][0] 1000
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
# ------------------------------------------------------------------------------------------------------------

data modify storage bs:lambda spline.point set value [0d, 0d]
execute store result score #x bs.ctx store result score #y bs.ctx run scoreboard players operation #t bs.ctx %= 1000 bs.const
execute store result score #x bs.ctx \
store result score #y bs.ctx \
run scoreboard players operation #t bs.ctx %= 1000 bs.const

execute store result score #a bs.ctx run data get storage bs:ctx _.points[0][0] 1000
execute store result score #c bs.ctx run data get storage bs:ctx _.points[1][0] 1000
Expand Down
Loading
Loading