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)]
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
struct TopLevel {
|
struct TopLevel {
|
||||||
blocks: Vec<Block>,
|
blocks: Vec<Block>,
|
||||||
collision_shapes: Vec<CollisionShape>,
|
shapes: Vec<Shape>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Clone, Debug)]
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
struct Block {
|
struct Block {
|
||||||
|
#[allow(unused)]
|
||||||
id: u16,
|
id: u16,
|
||||||
translation_key: String,
|
translation_key: String,
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -48,7 +49,7 @@ struct State {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Clone, Debug)]
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
struct CollisionShape {
|
struct Shape {
|
||||||
min_x: f64,
|
min_x: f64,
|
||||||
min_y: f64,
|
min_y: f64,
|
||||||
min_z: f64,
|
min_z: f64,
|
||||||
|
@ -58,10 +59,8 @@ struct CollisionShape {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build() -> anyhow::Result<TokenStream> {
|
pub fn build() -> anyhow::Result<TokenStream> {
|
||||||
let TopLevel {
|
let TopLevel { blocks, shapes } =
|
||||||
blocks,
|
serde_json::from_str(include_str!("../extracted/blocks.json"))?;
|
||||||
collision_shapes,
|
|
||||||
} = serde_json::from_str(include_str!("../extracted/blocks.json"))?;
|
|
||||||
|
|
||||||
let max_state_id = blocks.iter().map(|b| b.max_state_id()).max().unwrap();
|
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>();
|
.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
|
let get_arms = blocks
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&b| !b.properties.is_empty())
|
.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.
|
/// Constructs a block state from a raw block state ID.
|
||||||
///
|
///
|
||||||
/// If the given ID is invalid, `None` is returned.
|
/// If the given ID is invalid, `None` is returned.
|
||||||
|
@ -371,6 +421,14 @@ pub fn build() -> anyhow::Result<TokenStream> {
|
||||||
Self(id)
|
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.
|
/// Converts this block state to its underlying raw block state ID.
|
||||||
///
|
///
|
||||||
/// The original block state can be recovered with [`BlockState::from_raw`].
|
/// 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)
|
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
|
#default_block_states
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"collision_shapes": [
|
"shapes": [
|
||||||
{
|
{
|
||||||
"min_x": 0.0,
|
"min_x": 0.0,
|
||||||
"min_y": 0.0,
|
"min_y": 0.0,
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class Blocks implements Main.Extractor {
|
||||||
var blocksJson = new JsonArray();
|
var blocksJson = new JsonArray();
|
||||||
var stateIdCounter = 0;
|
var stateIdCounter = 0;
|
||||||
|
|
||||||
var collisionShapes = new LinkedHashMap<CollisionShape, Integer>();
|
var shapes = new LinkedHashMap<Shape, Integer>();
|
||||||
|
|
||||||
for (var block : Registry.BLOCK) {
|
for (var block : Registry.BLOCK) {
|
||||||
var blockJson = new JsonObject();
|
var blockJson = new JsonObject();
|
||||||
|
@ -68,10 +68,10 @@ public class Blocks implements Main.Extractor {
|
||||||
|
|
||||||
var collisionShapeIdxsJson = new JsonArray();
|
var collisionShapeIdxsJson = new JsonArray();
|
||||||
for (var box : state.getCollisionShape(EmptyBlockView.INSTANCE, BlockPos.ORIGIN).getBoundingBoxes()) {
|
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());
|
var idx = shapes.putIfAbsent(collisionShape, shapes.size());
|
||||||
collisionShapeIdxsJson.add(Objects.requireNonNullElseGet(idx, () -> collisionShapes.size() - 1));
|
collisionShapeIdxsJson.add(Objects.requireNonNullElseGet(idx, () -> shapes.size() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
stateJson.add("collision_shapes", collisionShapeIdxsJson);
|
stateJson.add("collision_shapes", collisionShapeIdxsJson);
|
||||||
|
@ -83,24 +83,24 @@ public class Blocks implements Main.Extractor {
|
||||||
blocksJson.add(blockJson);
|
blocksJson.add(blockJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
var collisionShapesJson = new JsonArray();
|
var shapesJson = new JsonArray();
|
||||||
for (var shape : collisionShapes.keySet()) {
|
for (var shape : shapes.keySet()) {
|
||||||
var collisionShapeJson = new JsonObject();
|
var shapeJson = new JsonObject();
|
||||||
collisionShapeJson.addProperty("min_x", shape.minX);
|
shapeJson.addProperty("min_x", shape.minX);
|
||||||
collisionShapeJson.addProperty("min_y", shape.minY);
|
shapeJson.addProperty("min_y", shape.minY);
|
||||||
collisionShapeJson.addProperty("min_z", shape.minZ);
|
shapeJson.addProperty("min_z", shape.minZ);
|
||||||
collisionShapeJson.addProperty("max_x", shape.maxX);
|
shapeJson.addProperty("max_x", shape.maxX);
|
||||||
collisionShapeJson.addProperty("max_y", shape.maxY);
|
shapeJson.addProperty("max_y", shape.maxY);
|
||||||
collisionShapeJson.addProperty("max_z", shape.maxZ);
|
shapeJson.addProperty("max_z", shape.maxZ);
|
||||||
collisionShapesJson.add(collisionShapeJson);
|
shapesJson.add(shapeJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
topLevelJson.add("collision_shapes", collisionShapesJson);
|
topLevelJson.add("shapes", shapesJson);
|
||||||
topLevelJson.add("blocks", blocksJson);
|
topLevelJson.add("blocks", blocksJson);
|
||||||
|
|
||||||
return topLevelJson;
|
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::fmt::{self, Display};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
use std::iter::FusedIterator;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue