Skip to content

Commit

Permalink
feat(block): Block API and stone, grass block, dirt.
Browse files Browse the repository at this point in the history
perf: use fastrand instead of rand to generate entity id.
  • Loading branch information
Liyze09 committed Sep 15, 2024
1 parent b4f0096 commit c11c6e3
Show file tree
Hide file tree
Showing 11 changed files with 294 additions and 81 deletions.
65 changes: 7 additions & 58 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ serde = "1.0.210"
serde_json = "1.0.128"
serde_derive = "1.0.210"
static-files = "0.2.4"
rand = "0.8.5"
fastrand = "2.1.1"
nohash-hasher = "0.2.0"
mimalloc = "0.1.43"
rayon = "1.10.0"
Expand All @@ -25,3 +25,6 @@ hashbrown = "0.14.5"

[build-dependencies]
static-files = "0.2.4"

[profile.release]
lto = "fat"
173 changes: 154 additions & 19 deletions src/block.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,82 @@
pub mod dirt;
pub mod grass_block;
pub mod stone;

use crate::registry::protocol_id::{get_block_states, get_protocol_id};
use crate::world::block_update::BlockUpdateType;
use crate::world::dimension::Dimension;
use dashmap::DashMap;
use downcast_rs::{impl_downcast, DowncastSync};
use hashbrown::HashMap;
use once_cell::sync::Lazy;
use serde::de::DeserializeOwned;
use std::sync::Arc;

pub trait Block: Send + Sync {
pub trait Block: Send + Sync + DowncastSync {
fn when_block_update(
&self,
update_type: BlockUpdateType,
pos: (i32, i32, i32),
dimension: &mut Dimension,
state: u32,
);
fn get_block_id(&self) -> u32;
fn get_default_block_state(&self) -> u32;
fn get_block_states(&self) -> HashMap<u32, Box<(dyn BlockState)>>;
fn get_block_settings(&self) -> BlockSettings;
_update_type: BlockUpdateType,
_pos: (i32, i32, i32),
_dimension: &mut Dimension,
_state: u32,
) {
}
fn get_builder(&self) -> &BlockBuilder;
fn get_block_id(&self) -> u32 {
self.get_builder().protocol_id
}
fn get_default_block_state(&self) -> u32 {
self.get_builder().default_state
}
fn get_block_states(&self) -> &HashMap<u32, Arc<(dyn BlockState)>> {
&self.get_builder().block_states
}
fn get_block_settings(&self) -> &BlockSettings {
&self.get_builder().block_settings
}
}
pub trait BlockState: Send + Sync {
impl_downcast!(sync Block);
pub trait BlockState: Send + Sync + DowncastSync {
fn get_block_id(&self) -> u32;
fn get_block_state(&self) -> u32;
fn is_default(&self) -> bool;
}
pub(crate) static BLOCKS_BY_ID: Lazy<DashMap<String, Box<dyn Block>>> = Lazy::new(DashMap::new);
pub(crate) static BLOCKS_BY_NAME: Lazy<DashMap<u32, String>> = Lazy::new(DashMap::new);
pub(crate) static BLOCK_STATES_BY_ID: Lazy<DashMap<u32, Box<(dyn BlockState)>>> =
impl_downcast!(sync BlockState);

pub(crate) static BLOCKS_BY_ID: Lazy<DashMap<u32, Box<dyn Block>>> = Lazy::new(DashMap::new);
pub(crate) static BLOCKS_BY_NAME: Lazy<DashMap<String, u32>> = Lazy::new(DashMap::new);
pub(crate) static BLOCK_STATES_BY_ID: Lazy<DashMap<u32, Arc<(dyn BlockState)>>> =
Lazy::new(DashMap::new);

fn register_block(id: String, block: Box<dyn Block + 'static>) {
pub fn register_block(id: &str, block: Box<dyn Block + 'static>) {
block.get_block_states().into_iter().for_each(|(k, v)| {
BLOCK_STATES_BY_ID.insert(k, v);
BLOCK_STATES_BY_ID.insert(*k, v.clone());
});
BLOCKS_BY_NAME.insert(block.get_block_id(), id.clone());
BLOCKS_BY_ID.insert(id.clone(), block);
let protocol_id = block.get_block_id();
BLOCKS_BY_NAME.insert(id.to_string(), protocol_id);
BLOCKS_BY_ID.insert(protocol_id, block);
}

pub struct BlockBuilder {
pub protocol_id: u32,
pub default_state: u32,
pub block_states: HashMap<u32, Arc<(dyn BlockState)>>,
pub block_settings: BlockSettings,
}
impl BlockBuilder {
pub fn new<T: 'static + BlockState + DeserializeOwned>(
id: &str,
block_settings: BlockSettings,
) -> BlockBuilder {
let protocol_id = get_protocol_id("minecraft:block", &id).unwrap();
let (block_states, default_state) = get_block_states::<T>(&id);
BlockBuilder {
protocol_id,
default_state,
block_states,
block_settings,
}
}
}

pub enum BlockType {
Expand All @@ -43,6 +88,96 @@ pub enum BlockType {
pub struct BlockSettings {
pub hardness: f32,
pub resistance: f32,
pub light_level: Option<u8>,
pub light_level: u8,
pub block_type: BlockType,
}
impl BlockSettings {
pub fn new() -> BlockSettings {
BlockSettings {
hardness: 6.0,
resistance: 6.0,
light_level: 0,
block_type: BlockType::Solid,
}
}
pub fn hardness(mut self, hardness: f32) -> BlockSettings {
self.hardness = hardness;
self
}
pub fn resistance(mut self, resistance: f32) -> BlockSettings {
self.resistance = resistance;
self
}
pub fn light_level(mut self, light_level: u8) -> BlockSettings {
self.light_level = light_level;
self
}
pub fn block_type(mut self, block_type: BlockType) -> BlockSettings {
self.block_type = block_type;
self
}
pub fn strength(mut self, strength: f32) -> BlockSettings {
self.hardness = strength;
self.resistance = strength;
self
}
}

impl Default for BlockSettings {
fn default() -> Self {
BlockSettings::new()
}
}

#[macro_export]
macro_rules! block_state {
($name:tt, $properties:ident, $id:expr) => {
#[derive(Deserialize)]
pub struct $name {
pub properties: $properties,
#[serde(default)]
pub default: bool,
pub id: u32,
}

impl BlockState for $name {
fn get_block_id(&self) -> u32 {
*BLOCKS_BY_NAME.get($id).unwrap()
}

fn get_block_state(&self) -> u32 {
self.id
}

fn is_default(&self) -> bool {
self.default
}
}
};
}

#[macro_export]
macro_rules! empty_block_state {
($name:tt, $id:expr) => {
#[derive(Deserialize)]
pub struct $name {
#[serde(default)]
pub default: bool,
pub id: u32,
}

impl BlockState for $name {
fn get_block_id(&self) -> u32 {
*BLOCKS_BY_NAME.get($id).unwrap()
}

fn get_block_state(&self) -> u32 {
self.id
}

fn is_default(&self) -> bool {
self.default
}
}
};
}
22 changes: 22 additions & 0 deletions src/block/dirt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::block::*;
use crate::empty_block_state;
pub(crate) const DIRT: &str = "minecraft:dirt";
pub struct Dirt {
pub builder: BlockBuilder,
}

impl Dirt {
pub(crate) fn new() -> Dirt {
Dirt {
builder: BlockBuilder::new::<DirtBlockState>(DIRT, BlockSettings::new().strength(0.6)),
}
}
}

impl Block for Dirt {
fn get_builder(&self) -> &BlockBuilder {
&self.builder
}
}

empty_block_state!(DirtBlockState, DIRT);
34 changes: 34 additions & 0 deletions src/block/grass_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use crate::block::{Block, BlockBuilder, BlockSettings, BlockState, BLOCKS_BY_NAME};
use crate::block_state;
use serde_derive::Deserialize;

pub(crate) const GRASS_BLOCK: &str = "minecraft:grass_block";
pub struct GrassBlock {
pub builder: BlockBuilder,
}
impl GrassBlock {
pub(crate) fn new() -> GrassBlock {
GrassBlock {
builder: BlockBuilder::new::<GrassBlockState>(
GRASS_BLOCK,
BlockSettings::new().strength(0.6),
),
}
}
}
impl Block for GrassBlock {
fn get_builder(&self) -> &BlockBuilder {
&self.builder
}
}

#[derive(Deserialize)]
pub struct GrassBlockStateProperties {
pub snowy: bool,
}

block_state! {
GrassBlockState,
GrassBlockStateProperties,
GRASS_BLOCK
}
Loading

0 comments on commit c11c6e3

Please sign in to comment.