BlockId refactor.

Moved `BlockId` to it's own file.
Prefixed all of the `block_registry` types with Registry to avoid confusion.
Made stuff that should not be public private.
This commit is contained in:
DaniD3v 2024-08-26 13:47:56 +02:00
parent bef3ddef50
commit cf283323fc
6 changed files with 82 additions and 81 deletions

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use crate::{bytebuf::ByteBuffer, BitSet, ClientPacket, VarInt}; use crate::{bytebuf::ByteBuffer, BitSet, ClientPacket, VarInt};
use itertools::Itertools; use itertools::Itertools;
use pumpkin_macros::packet; use pumpkin_macros::packet;
use pumpkin_world::{block::block_registry::BlockId, chunk::ChunkData, DIRECT_PALETTE_BITS}; use pumpkin_world::{chunk::ChunkData, DIRECT_PALETTE_BITS};
#[packet(0x27)] #[packet(0x27)]
pub struct CChunkData<'a>(pub &'a ChunkData); pub struct CChunkData<'a>(pub &'a ChunkData);
@ -23,15 +23,7 @@ impl<'a> ClientPacket for CChunkData<'a> {
let mut data_buf = ByteBuffer::empty(); let mut data_buf = ByteBuffer::empty();
self.0.blocks.iter_subchunks().for_each(|chunk| { self.0.blocks.iter_subchunks().for_each(|chunk| {
let block_count = chunk let block_count = chunk.iter().dedup().filter(|block| !block.is_air()).count() as i16;
.iter()
.dedup()
.filter(|block| {
!block.is_air()
&& **block != BlockId::from_id(12959)
&& **block != BlockId::from_id(12958)
})
.count() as i16;
// Block count // Block count
data_buf.put_i16(block_count); data_buf.put_i16(block_count);
//// Block states //// Block states

View File

@ -0,0 +1,58 @@
use std::collections::HashMap;
use serde::Deserialize;
use super::block_registry::BLOCKS;
use crate::level::WorldError;
// 0 is air -> reasonable default
#[derive(Default, Deserialize, Debug, Hash, Clone, Copy, PartialEq, Eq)]
#[serde(transparent)]
pub struct BlockId {
data: u16,
}
impl BlockId {
pub const AIR: Self = Self::from_id(0);
pub fn new(
text_id: &str,
properties: Option<&HashMap<String, String>>,
) -> Result<Self, WorldError> {
let mut block_states = BLOCKS
.get(text_id)
.ok_or(WorldError::BlockIdentifierNotFound)?
.states
.iter();
let block_state = match properties {
Some(properties) => match block_states.find(|state| &state.properties == properties) {
Some(state) => state,
None => return Err(WorldError::BlockStateIdNotFound),
},
None => block_states
.find(|state| state.is_default)
.expect("Every Block should have at least 1 default state"),
};
Ok(block_state.id)
}
pub const fn from_id(id: u16) -> Self {
// TODO: add check if the id is actually valid
Self { data: id }
}
pub fn is_air(&self) -> bool {
self.data == 0 || self.data == 12959 || self.data == 12958
}
pub fn get_id(&self) -> u16 {
self.data
}
/// An i32 is the way mojang internally represents their Blocks
pub fn get_id_mojang_repr(&self) -> i32 {
self.data as i32
}
}

View File

@ -3,101 +3,50 @@ use std::collections::HashMap;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use serde::Deserialize; use serde::Deserialize;
use crate::level::WorldError; use super::block_id::BlockId;
const BLOCKS_JSON: &str = include_str!("../../assets/blocks.json"); lazy_static! {
pub static ref BLOCKS: HashMap<String, RegistryBlockType> =
// 0 is air -> reasonable default serde_json::from_str(include_str!("../../assets/blocks.json"))
#[derive(Default, Deserialize, Debug, Hash, Clone, Copy, PartialEq, Eq)] .expect("Could not parse block.json registry.");
#[serde(transparent)]
pub struct BlockId {
data: u16,
}
impl BlockId {
pub fn new(
block_id: &str,
properties: Option<&HashMap<String, String>>,
) -> Result<Self, WorldError> {
let mut block_states = BLOCKS
.get(block_id)
.ok_or(WorldError::BlockIdentifierNotFound)?
.states
.iter();
let block_state = match properties {
Some(properties) => match block_states.find(|state| &state.properties == properties) {
Some(state) => state,
None => return Err(WorldError::BlockStateIdNotFound),
},
None => block_states
.find(|state| state.is_default)
.expect("Every Block should have at least 1 default state"),
};
Ok(block_state.id)
}
pub fn from_id(id: u16) -> Self {
// TODO: add check if the id is actually valid
Self { data: id }
}
pub fn is_air(&self) -> bool {
self.data == 0
}
pub fn get_id(&self) -> u16 {
self.data
}
/// An i32 is the way mojang internally represents their Blocks
pub fn get_id_mojang_repr(&self) -> i32 {
self.data as i32
}
} }
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)] #[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct BlockDefinition { pub struct RegistryBlockDefinition {
/// e.g. minecraft:door or minecraft:button /// e.g. minecraft:door or minecraft:button
#[serde(rename = "type")] #[serde(rename = "type")]
category: String, pub category: String,
/// Specifies the variant of the blocks category. /// Specifies the variant of the blocks category.
/// e.g. minecraft:iron_door has the variant iron /// e.g. minecraft:iron_door has the variant iron
#[serde(rename = "block_set_type")] #[serde(rename = "block_set_type")]
variant: Option<String>, pub variant: Option<String>,
} }
/// One possible state of a Block. /// One possible state of a Block.
/// This could e.g. be an extended piston facing left. /// This could e.g. be an extended piston facing left.
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)] #[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct BlockState { pub struct RegistryBlockState {
id: BlockId, pub id: BlockId,
/// Whether this is the default state of the Block /// Whether this is the default state of the Block
#[serde(default, rename = "default")] #[serde(default, rename = "default")]
is_default: bool, pub is_default: bool,
/// The propertise active for this `BlockState`. /// The propertise active for this `BlockState`.
#[serde(default)] #[serde(default)]
properties: HashMap<String, String>, pub properties: HashMap<String, String>,
} }
/// A fully-fledged block definition. /// A fully-fledged block definition.
/// Stores the category, variant, all of the possible states and all of the possible properties. /// Stores the category, variant, all of the possible states and all of the possible properties.
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)] #[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct BlockType { pub struct RegistryBlockType {
definition: BlockDefinition, pub definition: RegistryBlockDefinition,
states: Vec<BlockState>, pub states: Vec<RegistryBlockState>,
// TODO is this safe to remove? It's currently not used in the Project. @lukas0008 @Snowiiii // TODO is this safe to remove? It's currently not used in the Project. @lukas0008 @Snowiiii
/// A list of valid property keys/values for a block. /// A list of valid property keys/values for a block.
#[serde(default, rename = "properties")] #[serde(default, rename = "properties")]
valid_properties: HashMap<String, Vec<String>>, valid_properties: HashMap<String, Vec<String>>,
} }
lazy_static! {
pub static ref BLOCKS: HashMap<String, BlockType> =
serde_json::from_str(BLOCKS_JSON).expect("Could not parse block.json registry.");
}

View File

@ -1,9 +1,11 @@
use crate::vector3::Vector3;
use num_derive::FromPrimitive; use num_derive::FromPrimitive;
use crate::vector3::Vector3; pub mod block_id;
mod block_registry;
pub use block_id::BlockId;
pub mod block_registry;
pub use block_registry::BLOCKS;
#[derive(FromPrimitive)] #[derive(FromPrimitive)]
pub enum BlockFace { pub enum BlockFace {
Bottom = 0, Bottom = 0,

View File

@ -6,7 +6,7 @@ use fastnbt::LongArray;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
block::block_registry::BlockId, block::BlockId,
coordinates::{ChunkCoordinates, ChunkRelativeBlockCoordinates, Height}, coordinates::{ChunkCoordinates, ChunkRelativeBlockCoordinates, Height},
level::WorldError, level::WorldError,
WORLD_HEIGHT, WORLD_HEIGHT,

View File

@ -25,7 +25,7 @@ use pumpkin_protocol::{
SUseItemOn, Status, SUseItemOn, Status,
}, },
}; };
use pumpkin_world::block::{block_registry::BlockId, BlockFace}; use pumpkin_world::block::{BlockFace, BlockId};
use pumpkin_world::global_registry; use pumpkin_world::global_registry;
use super::PlayerConfig; use super::PlayerConfig;