Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
6b488c5
Bring over block placing behavior from ferrumc
MSKatKing Mar 29, 2026
9197b72
Fix errors
MSKatKing Mar 29, 2026
2c131d0
Formatting and clippy
MSKatKing Mar 29, 2026
edce21e
Add functions to block state id
MSKatKing Apr 1, 2026
155e07c
Implement block placing to test
MSKatKing Apr 1, 2026
c042da0
Add README documentation and unknown block warning
MSKatKing Apr 2, 2026
5ceb126
Remove need for min_specialization feature by implementing BlockBehav…
MSKatKing Apr 2, 2026
f9d2499
Formatting and clippy
MSKatKing Apr 2, 2026
1dbfc6a
Allow casting from BlockStateId to specific block struct
MSKatKing Apr 2, 2026
c1a1d9b
Merge branch 'temper-mc:master' into feature/block-updates
MSKatKing Apr 2, 2026
ed73bb8
Fix bugs with block behavior trait macro
MSKatKing Apr 3, 2026
3b6ed91
Remove test functions and move SlabBlock and SnowyBlock behavior impl…
MSKatKing Apr 4, 2026
a1117a2
Add more documentation
MSKatKing Apr 9, 2026
2801165
Merge branch 'temper-mc:master' into feature/block-updates
MSKatKing Apr 15, 2026
b2ab7f2
Merge remote-tracking branch 'temper/master' into feature/block-updates
MSKatKing May 7, 2026
7c09384
Resolve issues outside of block crate
MSKatKing May 7, 2026
835a9c6
Formatting fix
MSKatKing May 13, 2026
1ac4b1f
Remove inline(always)
MSKatKing May 28, 2026
c8e7d97
Add data crate for blocks
MSKatKing May 28, 2026
d049a30
Move PlacementContext struct to block data
MSKatKing May 28, 2026
3f78535
Update place block function
MSKatKing May 28, 2026
c01ec72
Fix some bugs with block placing
MSKatKing May 28, 2026
3363e1b
Merge remote-tracking branch 'temper/dev' into feature/block-updates
MSKatKing May 28, 2026
71e2e6d
Fix errors from merge
MSKatKing May 28, 2026
e2bc8b7
Move door code from block placing and interactions, remove old intera…
MSKatKing May 28, 2026
f8c0eb8
Fix block breaking bugs
MSKatKing May 28, 2026
c4efc8d
Cleanup and condense handlers
MSKatKing May 28, 2026
a742323
Ensure that can_be_replaced is properly used
MSKatKing May 29, 2026
947b5e9
Port fences/glass panes and logs to new system
MSKatKing May 29, 2026
03b4c00
Add roadmap for future versions of block system
MSKatKing May 29, 2026
a216ea5
Allow for reassigning simple blocks to new enums
MSKatKing May 29, 2026
15fbe74
Port torches to new system
MSKatKing May 29, 2026
b9c7837
Remove old block-placing crate
MSKatKing May 29, 2026
6c780b0
Added cache for cooldowns and fixed render distance
ReCore-sys Jun 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ members = [
"src/base/macros",
"src/base/profiling",
"src/base/threadpool",
"src/blocks",
"src/blocks/crates/property",
"src/blocks/crates/generated",
"src/blocks/crates/build",
"src/blocks/crates/data",
"src/bin",
"src/commands",
"src/components",
Expand Down Expand Up @@ -55,7 +60,6 @@ members = [
"src/text",
"src/utils",
"src/world",
"src/world/block-placing",
"src/world/db",
"src/world/format",
"src/world/gen",
Expand Down Expand Up @@ -119,6 +123,9 @@ debug = true
# Workspace members
temper-app = { path = "src/app" }
temper-anvil = { path = "src/adapters/anvil" }
temper-blocks = { path = "src/blocks" }
temper-block-properties = { path = "src/blocks/crates/property" }
temper-block-data = { path = "src/blocks/crates/data" }
temper-config = { path = "src/config" }
temper-core = { path = "src/core" }
temper-default-commands = { path = "src/default_commands" }
Expand Down Expand Up @@ -225,6 +232,7 @@ uuid = { version = "1.23.1", features = ["v4", "v3", "serde"] }
indexmap = { version = "2.14.0", features = ["serde"] }
bimap = "0.6.3"
arrayvec = "0.7.6"
fastcache = "0.1.7"

# Macros
lazy_static = "1.5.0"
Expand Down
2 changes: 1 addition & 1 deletion src/base/macros/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub fn command(attr: TokenStream, item: TokenStream) -> TokenStream {
if let Type::Path(path) = *refr.clone().elem {
println!("path reference: {:?}", path.path.segments.clone());
let is_bevy = path.path.segments.iter().any(|seg| {
println!("{}", &seg.ident.to_string());
println!("{}", seg.ident);
&seg.ident.to_string() == "bevy_ecs"
});
println!("is bevy? {is_bevy}");
Expand Down
21 changes: 21 additions & 0 deletions src/blocks/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "temper-blocks"
edition.workspace = true
version = "0.0.1"

[dependencies]
temper-world = { workspace = true }
temper-block-properties = { workspace = true }
temper-blocks-generated = { path = "crates/generated" }
temper-block-data = { workspace = true }
temper-core = { workspace = true }
temper-macros = { workspace = true }
bevy_math = { workspace = true }
tracing = { workspace = true }

[build-dependencies]
temper-blocks-build = { path = "crates/build" }
quote = { workspace = true }

[lints]
workspace = true
89 changes: 89 additions & 0 deletions src/blocks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Temper Blocks

This is a quick tutorial on how to use this library to create and modify block behavior and structs.

## Overview

This is a brief overview of what this crate is actually doing. This is split up into 2 distinct pieces,
the struct generator and the behavior implementation.

The struct generator (the `temper-blocks-build` crate) is given the `build_config.toml` and `blockstates.json` files
and generates structs based off of groups of blockstates. For each block in `blockstates.json`, it
figures out which properties that block has. It will then collect blocks that have those same properties
and group them under the same struct. When it's saving the structs, it will look at the `build_config.toml`
file and rename structs according to the names in that file. The `build_config.toml` also provides the struct
names of various block state properties. The list of block state properties Minecraft uses can be found at
`net.minecraft.world.level.block.state.properties.BlockStateProperties` (as of 1.21.11).

The next step is the block behavior implementations (this is the main crate). To add behavior to blocks, implement
the `BlockBehavior` trait for that block struct. The trait has already been implemented for all block
structs so far (to avoid unsafe features, such as `min_specialization`, it's not the most convenient, but it works).
The build script for this crate uses the `blockstates.json` file to generate a list that maps protocol ids (index)
to block states (value). This list is then used to dispatch behavior functions based on the protocol id.

This crate also implements a helper trait on `BlockStateId` that allows you to call block functions directly from it
(and it will also be updated if the function mutates the block state).

As a side note, the `temper-blocks-generated` crate contains the glue code to use the generated structs from
the build crate. The build crate outputs to the build directory and this crate imports those files back in.
Additionally, the `temper-block-properties` crate is where block state property structs and enums can be found.

Any data types used exclusively by this crate (for example, the `PlacedBlocks` struct) should be placed in the `temper-block-data` crate.

## Tips and Notes

- If the build script is emitting a warning about an unknown block, see the **Adding / Modifying Block Structs** section for more information.

## Creating Block Behavior

To create a new function for blocks to implement, navigate to the `behavior_trait.rs` file. Due to the complexity of the inner workings of the system, a macro has been built to make creating functions for blocks super easy. The macro syntax is pretty simple:

```rust
block_behavior_trait!(
fn <function name>([mut]; <arguments>) [-> <return type>; {<default return value}],
...
);
```

- Function Name: The name of the function.
- mut: Optional; whether the function should allow blocks to be mutated. Note: the semicolon after mut is required whether mut is specified or not.
- Arguments: Any amount of arguments for the function to take in.
- Return Type: Optional; The return type of the function.
- Default Return Value: Only present if a return type is specified; the value returned by the default trait implementation of the function.

You can look at the existing functions for tips on usage as well. Simply add your function to this list for it to be a function that blocks can implement.

**PLEASE NOTE:** This macro should ***NOT*** be used anywhere else in the project. It is only here to autogenerate structs and function pointer types that are needed for function dispatch while making it easy to create and modify block functions.

## Implementing / Modifying Block Behavior

To implement or modify the behavior of a block, navigate to where the `BlockBehavior` trait is implemented for that block type.

**NOTE:** Not all blocks have their own block type/struct. Most blocks are lumped in to a single struct (for example, all slab blocks are implemented as the SlabBlock type). This is also how Minecraft implements this (blocks of the same type and logic are instantiated as the same class). Blocks can still be distinguished by the enum attached to the struct.

Once you find the `BlockBehavior` implementation, simply add or modify the function you want.

## Adding / Modifying Block Structs

To add a struct for a specific block type you must edit the `build_config.toml` file. Which section you edit is dependent on what you'd like to do. All blocks are placed into a struct no matter what, so you must either override the name or explicitly place the specific block type into a separate struct.

The `name_overrides` section is for assigning a name to a particular arrangement of block state properties. For example, slabs in the game have the block state properties `type` and `waterlogged`. The name `SlabBlock` was assigned to all blocks with that arrangement of block state properties.

**NOTE:** There are quite a few blocks that have completely different behavior to other blocks but share the same block state property configuration. In this situation, the `block_overrides` section may have to be used.

The `block_overrides` section is for placing specific blocks into different structs. If a block is placed here it will ignore any name given to its configuration of block state properties and use this name instead.

### Important Note

All block struct names **MUST** be unique. The generated crate will not compile otherwise.

## Roadmap

Here's a quick roadmap of features that are planned to be added in future versions of this crate:

- BlockBehavior generator macro as a proc-macro for 100% rust-style function definition syntax
- Better generator functions (like `get_placement_state`), make them more rust-like and return `Option<Self>` rather than mutating self directly
- Performance improvements and code-size reduction
- Better struct combination capabilities (combine structs with not identical properties, property serialization depends on the block type set)
- Note to self: this would be super useful for things like torches where they have two different blocks representing the same item. Combining TorchBlock and WallTorchBlock into just TorchBlock would be very helpful
- And of course, more block behavior functions!
40 changes: 40 additions & 0 deletions src/blocks/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use quote::__private::TokenStream;
use quote::quote;
use std::fs;
use std::path::Path;
use temper_blocks_build::complex::fill_complex_block_mappings;
use temper_blocks_build::config::{get_block_states, get_build_config};
use temper_blocks_build::separate_blocks;
use temper_blocks_build::simple::fill_simple_block_mappings;

fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=build_config.toml");

let build_config = get_build_config();
let block_states = get_block_states();

let mut mappings = Vec::with_capacity(block_states.len());
mappings.resize(block_states.len(), TokenStream::new());
let (simple_blocks, complex_blocks) = separate_blocks(block_states);

let enum_const = fill_simple_block_mappings(&build_config, simple_blocks, &mut mappings);
let complex_consts = fill_complex_block_mappings(&build_config, complex_blocks, &mut mappings);

let mapping_const = quote! {
{
use temper_blocks_generated::*;

#enum_const
#(#complex_consts)*

&[
#(#mappings),*
]
}
};

let out_dir = std::env::var_os("OUT_DIR").unwrap();
let dir = Path::new(&out_dir).join("mappings.rs");
fs::write(dir, mapping_const.to_string()).unwrap();
}
Loading
Loading