This commit is contained in:
2026-05-13 20:38:59 +03:00
parent 9055c9c93c
commit 5620324b2e
4904 changed files with 391162 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
Sable stores physics-related properties per block-state.
These properties are defined through definition JSONs in datapacks.
### Available Properties
The default available properties consist of:
- `sable:mass` - mass of the block in `kpg`. Default `1.0`
- `sable:inertia` - inertia multiplier of the block along each axis in `kpg*m^2`. Is multiplied by the mass of the block before usage. Default `[1/6, 1/6, 1/6]`
- `sable:volume` - the volume of the block in `m^3`. Used for buoyancy calculations. Default `1.0`
- `sable:restitution` - the bounciness of the block from 0-1. Default `0.0`
- `sable:friction` - the friction multiplier of the block. Default `1.0`
- `sable:fragile` - if the block should break upon impact. Default `false`
- `sable:floating_material` - the floating block material to assign. Default `null`
- `sable:floating_scale` - the multiplier for the floating block material. Default `1.0`
### JSON Structure
Block physics property definition JSONs can be put in any datapack under the `physics_block_properties` folder.
```js
// /data/examplemod/physics_block_properties/example_block.json
{
// The selector can either be a tag, or block ID.
// If a tag is used, all blocks in the tag will be effected.
// Ex. `#examplemod:example_blocks` or `examplemod:example_block`
"selector": "examplemod:example_block"
// Priority is default 1000.
// Definitions are applied in order of ascending priority
"priority": 1001,
"properties": {
// Any properties can be defined here
"sable:mass": 2.0
},
"overrides": {
// Override keys are block-state conditions
"lit=true": {
// Any properties can be defined here
// All block-states meeting the condition will be affected
"sable:mass": 3.0
}
}
}
```
### Examples
A block that bounces:
```js
// /data/examplemod/physics_block_properties/bouncy_block.json
{
"selector": "examplemod:bouncy_block",
"properties": {
"sable:restitution": 0.5
}
}
```
A piston that doesn't weigh as much when extended:
```js
// /data/examplemod/physics_block_properties/piston.json
{
"selector": "examplemod:piston",
"properties": {
"sable:mass": 1.0
},
"overrides": {
"extended=true": {
"sable:mass": 0.5
}
}
}
```
### Tags
Sable contains many block tags in its own built-in datapack for commonly used physics block properties.
It is suggested to put your block into the pre-defined tags, if you do not need custom property definitions:
- `#sable:super_light` mass = 0.25
- `#sable:light` mass = 0.5
- `#sable:heavy` mass = 2.0
- `#sable:super_heavy` mass = 4.0
- `#sable:half_volume` volume = 0.5
- `#sable:quarter_volume` volume = 0.25
- `#sable:slippery` friction = 0.0
- `#sable:bouncy` restitution = 0.5
+104
View File
@@ -0,0 +1,104 @@
Sable allows datapacks to specify custom physics parameters for dimensions. These are loaded from `/data/<namespace>/dimension_physics/<name>.json`.
### Fields
**`dimension`** (required): The resource location of the dimension this config applies to.
**`priority`** (optional, default `1000`): When multiple configs target the same dimension, the one with the highest priority wins. Sable's built-in defaults use priority `0`, so any datapack config overrides them automatically.
**`base_gravity`** (optional, default `[0.0, -11.0, 0.0]`): Gravitational acceleration as a 3D vector in m/sec². The default pulls straight down at 11 m/s².
**`base_pressure`** (optional, default `1.0`): The pressure multiplier applied everywhere in the dimension. Set to `0` for a vacuum. If `pressure_function` is also defined, the two combine.
**`pressure_function`** (optional): A list of bezier control points for controlling air pressure with altitude. Each point has `altitude` (y-level), `value` (pressure at that altitude), and `slope` (rate of change). Omit this field for uniform pressure at `base_pressure`.
**`universal_drag`** (optional, default `0.09`): A flat drag coefficient applied to all motion in the dimension.
**`magnetic_north`** (optional, default `[0.0, 0.0, 0.0]`): Direction vector pointing toward magnetic north. `[0, 0, 0]` means no magnetic field.
### Examples
A moon dimension with lower gravity, no drag, and no air pressure:
```js
// /data/examplemod/dimension_physics/moon.json
{
"dimension": "examplemod:moon",
// Default priority of 1000
// Higher priority configs "win"
"priority": 1000,
// Modify the gravity to be low
"base_gravity": [0.0, -4.0, 0.0],
// No air pressure
"base_pressure": 0.0,
// No universal drag
"universal_drag": 0.0,
// No magnetic north
"magnetic_north": [0.0, 0.0, 0.0]
}
```
### Built-in Defaults
Sable generates these configs for vanilla dimensions. They're shown here, with approximate values, for reference.
The `pressure_function` is a curve approximating an exponential decay, centered around sea level, clamped to at most 1.5 underground, with a 40-meter smooth drop-off at the build limit.
**Overworld**:
```json
{
"dimension": "minecraft:overworld",
"priority": 0,
"universal_drag": 0.09,
"base_gravity": [0.0, -11.0, 0.0],
"base_pressure": 1.0,
"pressure_function": [
{ "altitude": -38.366277, "value": 1.5, "slope": -0.006 },
{ "altitude": 63.0, "value": 1.0, "slope": -0.004 },
{ "altitude": 263.0, "value": 0.449329, "slope": -0.001797 },
{ "altitude": 280.0, "value": 0.419786, "slope": -0.001679 },
{ "altitude": 320.0, "value": 0.0, "slope": -0.020989 }
],
"magnetic_north": [0.0, 0.0, 0.0]
}
```
**Nether**:
```json
{
"dimension": "minecraft:the_nether",
"priority": 0,
"universal_drag": 0.09,
"base_gravity": [0.0, -11.0, 0.0],
"base_pressure": 1.0,
"pressure_function": [
{ "altitude": 0.0, "value": 1.136553, "slope": -0.004546 },
{ "altitude": 32.0, "value": 1.0, "slope": -0.004 },
{ "altitude": 88.0, "value": 0.799315, "slope": -0.003197 },
{ "altitude": 128.0, "value": 0.0, "slope": -0.039966 }
],
"magnetic_north": [0.0, 0.0, 0.0]
}
```
**End**:
```json
{
"dimension": "minecraft:the_end",
"priority": 0,
"universal_drag": 0.09,
"base_gravity": [0.0, -11.0, 0.0],
"base_pressure": 1.0,
"pressure_function": [
{ "altitude": 0.0, "value": 1.0, "slope": -0.004 },
{ "altitude": 200.0, "value": 0.449329, "slope": -0.001797 },
{ "altitude": 216.0, "value": 0.421473, "slope": -0.001686 },
{ "altitude": 256.0, "value": 0.0, "slope": -0.021074 }
],
"magnetic_north": [0.0, 0.0, 0.0]
}
```
+95
View File
@@ -0,0 +1,95 @@
## Depending on Sable
[![Sable 1.21.1](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fmaven.ryanhcode.dev%2Freleases%2Fdev%2Fryanhcode%2Fsable%2Fsable-common-1.21.1%2Fmaven-metadata.xml&label=Sable%201.21.1)]([-1.21.1/](https://maven.ryanhcode.dev/releases/dev/ryanhcode/sable/sable-common-1.21.1/))
Copy the following segments into your `build.gradle` file depending on the platform:
### NeoForge
<details>
<summary>Click to expand</summary>
```groovy
repositories {
exclusiveContent { // Sable
forRepository {
maven {
url = "https://maven.ryanhcode.dev/releases"
name = "RyanHCode Maven"
}
}
filter {
includeGroup("dev.ryanhcode.sable")
includeGroup("dev.ryanhcode.sable-companion")
}
}
}
dependencies {
api("dev.ryanhcode.sable:sable-common-${project.minecraft_version}:${project.sable_version}")
}
```
</details>
### Fabric
<details>
<summary>Click to expand</summary>
```groovy
repositories {
exclusiveContent { // Sable
forRepository {
maven {
url = "https://maven.ryanhcode.dev/releases"
name = "RyanHCode Maven"
}
}
filter {
includeGroup("dev.ryanhcode.sable")
includeGroup("dev.ryanhcode.sable-companion")
}
}
}
dependencies {
modApi("dev.ryanhcode.sable:sable-fabric-${project.minecraft_version}:${project.sable_version}")
}
```
</details>
### Common
<details>
<summary>Click to expand</summary>
```groovy
repositories {
exclusiveContent { // Sable
forRepository {
maven {
url = "https://maven.ryanhcode.dev/releases"
name = "RyanHCode Maven"
}
}
filter {
includeGroup("dev.ryanhcode.sable")
includeGroup("dev.ryanhcode.sable-companion")
}
}
}
dependencies {
api "dev.ryanhcode.sable:sable-common-${project.minecraft_version}:${project.sable_version}"
}
```
</details>
### Working with Sable
- Simple compatability with [Sable Companion](https://github.com/ryanhcode/sable-companion)
- [Working with Entities](https://github.com/ryanhcode/sable/wiki/Working-With-Entities)
- [Block Physics Properties](https://github.com/ryanhcode/sable/wiki/Block-Physics-Properties)
- [Dimension Physics Data](https://github.com/ryanhcode/sable/wiki/Dimension-Physics-Data)
+41
View File
@@ -0,0 +1,41 @@
## "Entity Kicking"
Sable, by default, will "kick" all entities that are spawned inside the plot of a sub-level to global space.
This teleports the entity to its global position, applies velocity from the sub-level, and transforms the velocity and rotation of the entity out of the sub-level.
For some entities, such as Paintings or Armor Stands, this behavior is undesired, and the intended outcome is for the entity to stay inside the sub-level.
Sable therefore has tags to customize how entities interact with entity kicking:
- `#sable:retain_in_sub_level` - Never kick this entity from sub-levels. (ex. Armor Stands, Paintings)
- `#sable:destroy_when_leaving_plot` - Destroy this entity when it is inside a sub-level plot, but exits the bounds containing the sub-level blocks.
- `#sable:destroy_with_sub_level` - Destroy this entity when the sub-level plot containing it is destroyed, instead of kicking it to the global world. (ex. Super Glue from Create)
### Examples
To specify that an entity should stay inside of sub-level plots, and should never be kicked:
```js
// /data/sable/tags/entity_type/retain_in_sub_level.json
{
"replace": false,
"values": [
"examplemod:example_entity"
]
}
```
## Tracking
Entities can be *outside* of the plot of a sub-level, but still move with the sub-level (ex. A player standing on a sub-level, or a cow in a pen on a sub-level). When entities are standing on sub-levels, Sable marks them as "tracking" the sub-level.
Entities that are tracking a sub-level:
- Are networked relative to the sub-level
- Are interpolated relative to the sub-level
- Will move with the sub-level as it rotates and translates
Players that are tracking a sub-level will additionally log-out and log-in with a position relative to the sub-level through the tracking points system.
Sable has utilities to check the tracking sub-level of an entity:
```java
Entity entity = ...;
SubLevel subLevel = EntitySubLevelUtil.getTrackingSubLevel(this.entity);
```