mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 14:31:30 +11:00
Add collision shapes to block states
This commit is contained in:
parent
c1857e1603
commit
9c67978e06
119
build/block.rs
119
build/block.rs
|
@ -10,11 +10,12 @@ use crate::ident;
|
|||
#[derive(Deserialize, Clone, Debug)]
|
||||
struct TopLevel {
|
||||
blocks: Vec<Block>,
|
||||
collision_shapes: Vec<CollisionShape>,
|
||||
shapes: Vec<Shape>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
struct Block {
|
||||
#[allow(unused)]
|
||||
id: u16,
|
||||
translation_key: String,
|
||||
name: String,
|
||||
|
@ -48,7 +49,7 @@ struct State {
|
|||
}
|
||||
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
struct CollisionShape {
|
||||
struct Shape {
|
||||
min_x: f64,
|
||||
min_y: f64,
|
||||
min_z: f64,
|
||||
|
@ -58,10 +59,8 @@ struct CollisionShape {
|
|||
}
|
||||
|
||||
pub fn build() -> anyhow::Result<TokenStream> {
|
||||
let TopLevel {
|
||||
blocks,
|
||||
collision_shapes,
|
||||
} = serde_json::from_str(include_str!("../extracted/blocks.json"))?;
|
||||
let TopLevel { blocks, shapes } =
|
||||
serde_json::from_str(include_str!("../extracted/blocks.json"))?;
|
||||
|
||||
let max_state_id = blocks.iter().map(|b| b.max_state_id()).max().unwrap();
|
||||
|
||||
|
@ -77,6 +76,65 @@ pub fn build() -> anyhow::Result<TokenStream> {
|
|||
})
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let state_to_luminance_arms = blocks
|
||||
.iter()
|
||||
.flat_map(|b| {
|
||||
b.states.iter().filter(|s| s.luminance != 0).map(|s| {
|
||||
let id = s.id;
|
||||
let luminance = s.luminance;
|
||||
quote! {
|
||||
#id => #luminance,
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let state_to_opaque_arms = blocks
|
||||
.iter()
|
||||
.flat_map(|b| {
|
||||
b.states.iter().filter(|s| !s.opaque).map(|s| {
|
||||
let id = s.id;
|
||||
quote! {
|
||||
#id => false,
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let shapes = shapes.iter().map(|s| {
|
||||
let min_x = s.min_x;
|
||||
let min_y = s.min_y;
|
||||
let min_z = s.min_z;
|
||||
let max_x = s.max_x;
|
||||
let max_y = s.max_y;
|
||||
let max_z = s.max_z;
|
||||
quote! {
|
||||
[
|
||||
#min_x,
|
||||
#min_y,
|
||||
#min_z,
|
||||
#max_x,
|
||||
#max_y,
|
||||
#max_z,
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
let shape_count = shapes.len();
|
||||
|
||||
let state_to_collision_shapes_arms = blocks
|
||||
.iter()
|
||||
.flat_map(|b| {
|
||||
b.states.iter().map(|s| {
|
||||
let id = s.id;
|
||||
let collision_shapes = &s.collision_shapes;
|
||||
quote! {
|
||||
#id => &[#(#collision_shapes),*],
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let get_arms = blocks
|
||||
.iter()
|
||||
.filter(|&b| !b.properties.is_empty())
|
||||
|
@ -347,14 +405,6 @@ pub fn build() -> anyhow::Result<TokenStream> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the [`BlockKind`] of this block state.
|
||||
pub const fn to_kind(self) -> BlockKind {
|
||||
match self.0 {
|
||||
#state_to_kind_arms
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a block state from a raw block state ID.
|
||||
///
|
||||
/// If the given ID is invalid, `None` is returned.
|
||||
|
@ -371,6 +421,14 @@ pub fn build() -> anyhow::Result<TokenStream> {
|
|||
Self(id)
|
||||
}
|
||||
|
||||
/// Returns the [`BlockKind`] of this block state.
|
||||
pub const fn to_kind(self) -> BlockKind {
|
||||
match self.0 {
|
||||
#state_to_kind_arms
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts this block state to its underlying raw block state ID.
|
||||
///
|
||||
/// The original block state can be recovered with [`BlockState::from_raw`].
|
||||
|
@ -420,6 +478,39 @@ pub fn build() -> anyhow::Result<TokenStream> {
|
|||
matches!(self.to_kind(), BlockKind::Water | BlockKind::Lava)
|
||||
}
|
||||
|
||||
pub const fn is_opaque(self) -> bool {
|
||||
match self.0 {
|
||||
#state_to_opaque_arms
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
const SHAPES: [[f64; 6]; #shape_count] = [
|
||||
#(#shapes,)*
|
||||
];
|
||||
|
||||
pub fn collision_shapes(self) -> impl ExactSizeIterator<Item = vek::Aabb<f64>> + FusedIterator + Clone {
|
||||
let shape_idxs: &'static [u16] = match self.0 {
|
||||
#state_to_collision_shapes_arms
|
||||
_ => &[],
|
||||
};
|
||||
|
||||
shape_idxs.iter().map(|idx| {
|
||||
let [min_x, min_y, min_z, max_x, max_y, max_z] = Self::SHAPES[*idx as usize];
|
||||
vek::Aabb {
|
||||
min: vek::Vec3::new(min_x, min_y, min_z),
|
||||
max: vek::Vec3::new(max_x, max_y, max_z),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub const fn luminance(self) -> u8 {
|
||||
match self.0 {
|
||||
#state_to_luminance_arms
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#default_block_states
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"collision_shapes": [
|
||||
"shapes": [
|
||||
{
|
||||
"min_x": 0.0,
|
||||
"min_y": 0.0,
|
||||
|
|
|
@ -28,7 +28,7 @@ public class Blocks implements Main.Extractor {
|
|||
var blocksJson = new JsonArray();
|
||||
var stateIdCounter = 0;
|
||||
|
||||
var collisionShapes = new LinkedHashMap<CollisionShape, Integer>();
|
||||
var shapes = new LinkedHashMap<Shape, Integer>();
|
||||
|
||||
for (var block : Registry.BLOCK) {
|
||||
var blockJson = new JsonObject();
|
||||
|
@ -68,10 +68,10 @@ public class Blocks implements Main.Extractor {
|
|||
|
||||
var collisionShapeIdxsJson = new JsonArray();
|
||||
for (var box : state.getCollisionShape(EmptyBlockView.INSTANCE, BlockPos.ORIGIN).getBoundingBoxes()) {
|
||||
var cs = new CollisionShape(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ);
|
||||
var collisionShape = new Shape(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ);
|
||||
|
||||
var idx = collisionShapes.putIfAbsent(cs, collisionShapes.size());
|
||||
collisionShapeIdxsJson.add(Objects.requireNonNullElseGet(idx, () -> collisionShapes.size() - 1));
|
||||
var idx = shapes.putIfAbsent(collisionShape, shapes.size());
|
||||
collisionShapeIdxsJson.add(Objects.requireNonNullElseGet(idx, () -> shapes.size() - 1));
|
||||
}
|
||||
|
||||
stateJson.add("collision_shapes", collisionShapeIdxsJson);
|
||||
|
@ -83,24 +83,24 @@ public class Blocks implements Main.Extractor {
|
|||
blocksJson.add(blockJson);
|
||||
}
|
||||
|
||||
var collisionShapesJson = new JsonArray();
|
||||
for (var shape : collisionShapes.keySet()) {
|
||||
var collisionShapeJson = new JsonObject();
|
||||
collisionShapeJson.addProperty("min_x", shape.minX);
|
||||
collisionShapeJson.addProperty("min_y", shape.minY);
|
||||
collisionShapeJson.addProperty("min_z", shape.minZ);
|
||||
collisionShapeJson.addProperty("max_x", shape.maxX);
|
||||
collisionShapeJson.addProperty("max_y", shape.maxY);
|
||||
collisionShapeJson.addProperty("max_z", shape.maxZ);
|
||||
collisionShapesJson.add(collisionShapeJson);
|
||||
var shapesJson = new JsonArray();
|
||||
for (var shape : shapes.keySet()) {
|
||||
var shapeJson = new JsonObject();
|
||||
shapeJson.addProperty("min_x", shape.minX);
|
||||
shapeJson.addProperty("min_y", shape.minY);
|
||||
shapeJson.addProperty("min_z", shape.minZ);
|
||||
shapeJson.addProperty("max_x", shape.maxX);
|
||||
shapeJson.addProperty("max_y", shape.maxY);
|
||||
shapeJson.addProperty("max_z", shape.maxZ);
|
||||
shapesJson.add(shapeJson);
|
||||
}
|
||||
|
||||
topLevelJson.add("collision_shapes", collisionShapesJson);
|
||||
topLevelJson.add("shapes", shapesJson);
|
||||
topLevelJson.add("blocks", blocksJson);
|
||||
|
||||
return topLevelJson;
|
||||
}
|
||||
|
||||
private record CollisionShape(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
|
||||
private record Shape(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use std::fmt::{self, Display};
|
||||
use std::io::{Read, Write};
|
||||
use std::iter::FusedIterator;
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
|
|
Loading…
Reference in a new issue