From 9c67978e06d06627515888ec6061bf98c6825273 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 6 Aug 2022 16:46:07 -0700 Subject: [PATCH] Add collision shapes to block states --- build/block.rs | 119 +++++++++++++++--- extracted/blocks.json | 2 +- .../valence_extractor/extractors/Blocks.java | 32 ++--- src/block.rs | 1 + 4 files changed, 123 insertions(+), 31 deletions(-) diff --git a/build/block.rs b/build/block.rs index 0bef2df..f76c9eb 100644 --- a/build/block.rs +++ b/build/block.rs @@ -10,11 +10,12 @@ use crate::ident; #[derive(Deserialize, Clone, Debug)] struct TopLevel { blocks: Vec, - collision_shapes: Vec, + shapes: Vec, } #[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 { - 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 { }) .collect::(); + 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::(); + + 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::(); + + 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::(); + let get_arms = blocks .iter() .filter(|&b| !b.properties.is_empty()) @@ -347,14 +405,6 @@ pub fn build() -> anyhow::Result { } } - /// 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 { 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 { 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> + 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 } diff --git a/extracted/blocks.json b/extracted/blocks.json index a3c1749..a1d9f4c 100644 --- a/extracted/blocks.json +++ b/extracted/blocks.json @@ -1,5 +1,5 @@ { - "collision_shapes": [ + "shapes": [ { "min_x": 0.0, "min_y": 0.0, diff --git a/extractor/src/main/java/dev/_00a/valence_extractor/extractors/Blocks.java b/extractor/src/main/java/dev/_00a/valence_extractor/extractors/Blocks.java index 7f504ab..13d1b71 100644 --- a/extractor/src/main/java/dev/_00a/valence_extractor/extractors/Blocks.java +++ b/extractor/src/main/java/dev/_00a/valence_extractor/extractors/Blocks.java @@ -28,7 +28,7 @@ public class Blocks implements Main.Extractor { var blocksJson = new JsonArray(); var stateIdCounter = 0; - var collisionShapes = new LinkedHashMap(); + var shapes = new LinkedHashMap(); 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) { } } diff --git a/src/block.rs b/src/block.rs index 29a293f..5da7371 100644 --- a/src/block.rs +++ b/src/block.rs @@ -4,6 +4,7 @@ use std::fmt::{self, Display}; use std::io::{Read, Write}; +use std::iter::FusedIterator; use anyhow::Context;