Add collision shapes to block states

This commit is contained in:
Ryan 2022-08-06 16:46:07 -07:00
parent c1857e1603
commit 9c67978e06
4 changed files with 123 additions and 31 deletions

View file

@ -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
}

View file

@ -1,5 +1,5 @@
{
"collision_shapes": [
"shapes": [
{
"min_x": 0.0,
"min_y": 0.0,

View file

@ -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) {
}
}

View file

@ -4,6 +4,7 @@
use std::fmt::{self, Display};
use std::io::{Read, Write};
use std::iter::FusedIterator;
use anyhow::Context;