Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
8a69961
Start work on density functions
CrabbyDisk Aug 24, 2025
779b314
feat(world_gen): Implement PerlinNoise and Xoroshiro128PlusPlus (#202)
Mcrtin Aug 24, 2025
ce283a1
feat: add next_bounded and next_u64 to Legacy random
Mcrtin Aug 24, 2025
33ac104
Fix MultiNoise process function
CrabbyDisk Aug 24, 2025
df27098
feat: introduce Point<T> for plerlin sampling
Mcrtin Aug 26, 2025
acd8604
add missing functions for traits to the random impls
Mcrtin Aug 27, 2025
9c5e871
feat: implement aquifier
Mcrtin Aug 27, 2025
999b712
add ore vein generation
Mcrtin Aug 27, 2025
b44ea5f
refactor: use bevy_math
Mcrtin Aug 30, 2025
7b07372
refactor: use itertools for sorting
Mcrtin Aug 30, 2025
a68055a
add normal noise
Mcrtin Sep 2, 2025
0c96c70
introduce const Structs for noise
Mcrtin Sep 2, 2025
a27d6f4
feat: add noises
Mcrtin Sep 2, 2025
e82f81f
fix: add namespace instanciation of NormalNoises
Mcrtin Sep 2, 2025
a79d519
feat: add overworld biomes
Mcrtin Sep 3, 2025
a8113d5
update aquifer and ore veins to new api
Mcrtin Sep 3, 2025
5c5f72b
feat: add surface system
Mcrtin Sep 7, 2025
c522d7c
refactor the surface system a bit
Mcrtin Sep 7, 2025
4027b6e
feat: carver
Mcrtin Sep 8, 2025
29c3616
introduce BiomeChunk and do a lil refactor
Mcrtin Sep 10, 2025
6fe59a8
refactor aquifer
Mcrtin Sep 11, 2025
4fb0bf8
refactor surface
Mcrtin Sep 11, 2025
4eab08b
refactor carver
Mcrtin Sep 11, 2025
6072543
refactor: move overworld code into overworld dir
Mcrtin Sep 11, 2025
fc416e9
add dfs for overworld; does not compile - i don't want to lose these …
Mcrtin Sep 12, 2025
c7bdbae
make it compile again
Mcrtin Sep 13, 2025
039f6fa
remove deprecated rng enums
Mcrtin Sep 13, 2025
356318a
hook up the dfs to the worldgen
Mcrtin Sep 13, 2025
cb561c4
fix some problems in worldgen
Mcrtin Sep 13, 2025
cec8d47
fixup the noise depth a bit
Mcrtin Sep 13, 2025
53d9ff5
Fixes for block setting
ReCore-sys Sep 13, 2025
2f43ec7
Merge branch 'master' into feature/terrain-gen
ReCore-sys Sep 13, 2025
bc0fced
feat: add Blendednoise
Mcrtin Sep 13, 2025
2082b51
implement legacy improved noise
Mcrtin Sep 13, 2025
66c6580
move dfs to OverworldBiomeNoise
Mcrtin Sep 13, 2025
e0619fd
fix clamp
Mcrtin Sep 13, 2025
6cf144a
fix spline
Mcrtin Sep 15, 2025
4b5a5cb
fix perlin_noise
Mcrtin Sep 16, 2025
d8f27f0
fix chunk gen not iterating over all blocks
Mcrtin Sep 16, 2025
5122e7e
feat: overworld surface rules
Mcrtin Sep 17, 2025
01f5b25
Added ephemeral database env var
ReCore-sys Sep 20, 2025
ac5a964
Made var require to be true
ReCore-sys Sep 20, 2025
8790730
Fix tests
ReCore-sys Sep 20, 2025
eeb4a76
Actually fix tests
ReCore-sys Sep 20, 2025
af3db47
finish surface rule impl
Mcrtin Sep 17, 2025
5af41b0
feat: overworld carver
Mcrtin Sep 24, 2025
18d6b93
feat: impl noisy biome source
Mcrtin Sep 24, 2025
1359085
feat: add iterpolation mekanism :D
Mcrtin Sep 24, 2025
3d43f80
add placement_mod for features
Mcrtin Sep 27, 2025
4682229
refactor: refactor noise and random to be more const frendly
Mcrtin Sep 27, 2025
9d11e20
work on perlin and aquifer and add some things from decoration
Mcrtin Oct 3, 2025
adc4966
add surface rules into the system
Mcrtin Oct 3, 2025
636cd87
feat: implement interpolation
Mcrtin Oct 4, 2025
ef7165b
fix: send data
Mcrtin Oct 6, 2025
93331e2
finish noise generation setup
Mcrtin Oct 9, 2025
614d91f
refactor perlin_noise a bit
Mcrtin Oct 10, 2025
020291e
feat: compute prelim_surface directly
Mcrtin Oct 15, 2025
4a5f6f1
Add domain links to README
Sweattypalms Sep 16, 2025
4b7d167
Update README
ReCore-sys Sep 19, 2025
92e6f4b
Minify JSON files
ReCore-sys Oct 3, 2025
1eb8f21
cleanup unused crates
lexeyOK Oct 4, 2025
116bac2
feat: lan pinging
radstevee Oct 3, 2025
bf833f2
fix: lan pinging still being on the main thread
radstevee Oct 5, 2025
46bb2b2
turns out we don't need allat
radstevee Oct 5, 2025
c692aa8
fix: that does Not need to be a resource
radstevee Oct 5, 2025
17ca1ac
fix: it's over
radstevee Oct 5, 2025
b3a6d59
add verbose to runners in ci
lexeyOK Oct 11, 2025
3d4c42a
use checksum-freshness in builds
lexeyOK Oct 11, 2025
cfb1b3a
change manual cach to use Swatinem/rust-cache@v2, remove checksum-fre…
lexeyOK Oct 11, 2025
480856e
remove verbose flag
lexeyOK Oct 11, 2025
654859a
use sccache-action to cache the compiler runs
lexeyOK Oct 11, 2025
21dad5b
remove sccache
lexeyOK Oct 11, 2025
24522a4
implement biome temp
Mcrtin Oct 21, 2025
0b9b52c
Merge remote-tracking branch 'upstream/master' into feature/terrain-gen
Mcrtin Oct 28, 2025
6b88b01
use new block! macro
Mcrtin Oct 28, 2025
b9772c7
simplyfy lowest_pref_value_factor
Mcrtin Nov 2, 2025
0cafe80
feat: add biome temps
Mcrtin Nov 3, 2025
4763b29
make chunk_height const
Mcrtin Nov 3, 2025
5c9cbdd
fix: speed up the block! and block_match! macro
lexeyOK Oct 31, 2025
cdd9ab9
placeholders and multi-value
lexeyOK Nov 6, 2025
5dfbcbf
add .. to allow skip missing properties
lexeyOK Nov 7, 2025
a7f113b
add _ in props position and use `block!` macro in worldgen crate
lexeyOK Nov 7, 2025
cf5f429
feat: reimplementation of `block_data`
lexeyOK Nov 16, 2025
c86796d
Merge lexeyOk/master branch
lexeyOK Nov 16, 2025
cefa128
Merge branch 'master' of github.com:lexeyOK/ferrumc into feat/ng-chunk
lexeyOK Nov 16, 2025
3c7a949
fix edit_batch merge
lexeyOK Nov 16, 2025
9398261
fix edit_batch merge
lexeyOK Nov 16, 2025
71ede52
Merge branch 'feat/ng-chunk' of github.com:lexeyOK/ferrumc into feat/…
lexeyOK Nov 16, 2025
aee5111
fmt fix
lexeyOK Nov 16, 2025
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
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ result-*
profile.json.gz
.DS_Store

/world
whitelist.txt

logs/
Expand Down
12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,12 @@ resolver = "2"
members = [
"src/bin",
"src/lib/adapters/anvil",
"src/lib/adapters/anvil",
"src/lib/adapters/nbt",
"src/lib/adapters/nbt",
"src/lib/commands",
"src/lib/default_commands",
"src/lib/core",
"src/lib/core/state",
"src/lib/derive_macros",
"src/lib/derive_macros",
"src/lib/net",
"src/lib/net/crates/codec",
"src/lib/net/crates/encryption",
Expand All @@ -39,6 +36,7 @@ members = [
"src/lib/inventories",
"src/lib/registry",
"src/lib/scheduler",
"src/tests",
]

#================== Lints ==================#
Expand Down Expand Up @@ -141,6 +139,7 @@ rand = "0.10.0-rc.0"
fnv = "1.0.7"
wyhash = "0.6.0"
ahash = "0.8.12"
cthash = "0.9.0"

# Encoding/Serialization
serde = { version = "1.0.228", features = ["derive"] }
Expand Down Expand Up @@ -196,14 +195,15 @@ colored = "3.0.0"
deepsize = "0.2.0"
page_size = "0.6.0"
enum-ordinalize = "4.3.0"
regex = "1.12.2"
noise = "0.9.0"
ctrlc = "3.5.0"
regex = "1.11.1"
ctrlc = "3.4.7"
num_cpus = "1.17.0"
typename = "0.1.2"
bevy_ecs = { version = "0.16.1", features = ["multi_threaded", "trace"] }
bevy_math = "0.16.1"
once_cell = "1.21.3"
itertools = "0.14.0"
const-str = "0.7.0"

# I/O
memmap2 = "0.9.8"
Expand Down
Binary file removed assets/data/icon.png
Binary file not shown.
1 change: 1 addition & 0 deletions src/bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ thiserror = { workspace = true }

ferrumc-core = { workspace = true }
bevy_ecs = { workspace = true }
bevy_math = { workspace = true }
ferrumc-scheduler = { workspace = true }

ferrumc-net = { workspace = true }
Expand Down
10 changes: 3 additions & 7 deletions src/bin/src/packet_handlers/play_packets/place_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn handle(
match event.hand.0 {
0 => {
let slot_index = hotbar.selected_slot as usize;
let Ok(slot) = inventory.get_item(slot_index) else {
let Ok(slot) = inventory.get_item(slot_index + 36) else {
error!("Could not fetch {:?}", eid);
continue 'ev_loop;
};
Expand Down Expand Up @@ -78,9 +78,7 @@ pub fn handle(
}
};
let Ok(block_clicked) = chunk.get_block(
event.position.x,
event.position.y as i32,
event.position.z,
(event.position.x, event.position.y as i32, event.position.z).into(),
) else {
debug!("Failed to get block at position: {:?}", event.position);
continue 'ev_loop;
Expand Down Expand Up @@ -131,9 +129,7 @@ pub fn handle(
}

if let Err(err) = chunk.set_block(
x & 0xF,
y as i32,
z & 0xF,
(x, y as i32, z).into(),
BlockStateId(*mapped_block_state_id as u32),
) {
error!("Failed to set block: {:?}", err);
Expand Down
9 changes: 3 additions & 6 deletions src/bin/src/packet_handlers/play_packets/player_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,10 @@ pub fn handle(
.map_err(BinaryError::WorldGen)?
}
};
let (relative_x, relative_y, relative_z) = (
event.location.x.abs() % 16,
event.location.y as i32,
event.location.z.abs() % 16,
);
let relative =
(event.location.x, event.location.y as i32, event.location.z).into();
chunk
.set_block(relative_x, relative_y, relative_z, BlockStateId::default())
.set_block(relative, BlockStateId::default())
.map_err(BinaryError::World)?;
// Save the chunk to disk
state
Expand Down
9 changes: 6 additions & 3 deletions src/bin/src/packet_handlers/play_packets/player_loaded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ pub fn handle(
continue;
}
let head_block = state.0.world.get_block_and_fetch(
player_pos.x as i32,
player_pos.y as i32,
player_pos.z as i32,
(
player_pos.x as i32,
player_pos.y as i32,
player_pos.z as i32,
)
.into(),
"overworld",
);
if let Ok(head_block) = head_block {
Expand Down
5 changes: 5 additions & 0 deletions src/lib/derive_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ craftflow-nbt = { workspace = true }
indexmap = { workspace = true, features = ["serde"] }
bitcode = { workspace = true }
simd-json = { workspace = true }
phf = "0.13.1"

[dev-dependencies]
ferrumc-world = { workspace = true }

[build-dependencies]
phf_codegen = "0.13.1"
simd-json = { workspace = true }
80 changes: 80 additions & 0 deletions src/lib/derive_macros/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use std::{
collections::{HashMap, HashSet},
env,
fs::File,
io::{BufWriter, Write},
path::Path,
};

use simd_json::{
self,
base::{ValueAsObject, ValueAsScalar},
derived::ValueTryAsObject,
};

const JSON_FILE: &[u8] = include_bytes!("../../../assets/data/blockstates.json");

fn main() {
let mut buf = JSON_FILE.to_owned();
let v = simd_json::to_borrowed_value(&mut buf).unwrap();
let mut map = phf_codegen::Map::new();
let mut prop_map = phf_codegen::Map::new();
let mut rev_map: HashMap<String, Vec<u32>> = HashMap::new();
let mut rev_prop: HashMap<String, HashSet<String>> = HashMap::new();
for (key, value) in v.try_as_object().expect("object value") {
let id = key.parse::<u32>().expect("integer value");
let block = value.as_object().expect("object value");
let name = block
.get("name")
.expect("all block states have names")
.as_str()
.expect("names are strings")
.split_once("minecraft:")
.expect("names start with \"minecraft:\"")
.1;
let props = block.get("properties");
rev_map.entry(name.to_owned()).or_default().push(id);
rev_prop.entry(name.to_string()).or_default();
if let Some(props) = props {
for (prop_key, prop_val) in props.as_object().expect("properties is object") {
let map_key = format!("{}:{}", prop_key, prop_val);
rev_prop
.entry(prop_key.to_string())
.or_default()
.insert(prop_val.to_string());
rev_prop
.entry(name.to_string())
.or_default()
.insert(prop_key.to_string());
rev_map.entry(map_key).or_default().push(id);
}
}
}
for (k, v) in rev_map.iter_mut() {
v.sort();
map.entry(k.clone(), format!("&{:?}", v));
}

for (k, v) in rev_prop.iter() {
let mut v: Vec<String> = v.iter().cloned().collect();
v.sort();
prop_map.entry(k.clone(), format!("&{:?}", v));
}
let map = map.build();
let prop_map = prop_map.build();
let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs");
let mut file = BufWriter::new(File::create(&path).unwrap());
writeln!(
&mut file,
"static BLOCK_STATES: phf::Map<&'static str, &[u16]> = {};",
map
)
.expect("able to write to file");
writeln!(
&mut file,
"static PROP_PARTS: phf::Map<&'static str, &[&'static str]> = {};",
prop_map
)
.expect("able to write to file");
println!("created {}", &path.to_string_lossy());
}
50 changes: 19 additions & 31 deletions src/lib/derive_macros/src/block/matches.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use crate::block::JSON_FILE;
use crate::block::BLOCK_STATES;
use proc_macro::TokenStream;
use quote::quote;
use simd_json::base::{ValueAsObject, ValueAsScalar};
use simd_json::derived::ValueObjectAccess;

struct Input {
name: String,
Expand All @@ -21,42 +19,32 @@ impl syn::parse::Parse for Input {
}
}

// match_block!("stone", block_state_id); -> "if block_state_id == BlockStateId(1) { ... }
// match_block!("dirt", block_state_id); -> "if block_name == BlockStateId( { ... }
pub fn matches_block(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as Input);
let block_name = &input.name;
let block_name = if block_name.starts_with("minecraft:") {
block_name.to_string()
} else {
format!("minecraft:{}", block_name)
};
let block_state_id_var = &input.id_var;
let mut buf = JSON_FILE.to_vec();
let v = simd_json::to_owned_value(&mut buf).unwrap();
let filtered_names = v
.as_object()
.unwrap()
.iter()
.filter(|(_, v)| v.get("name").as_str() == Some(&block_name))
.map(|(k, v)| (k.parse::<u32>().unwrap(), v))
.collect::<Vec<_>>();
if filtered_names.is_empty() {
let block_name = input
.name
.split_once("minecraft:")
.map(|x| x.1)
.unwrap_or(input.name.as_str());
let block_id_var = &input.id_var;

let states = BLOCK_STATES.get(block_name);
if states.is_none_or(|x| x.is_empty()) {
return syn::Error::new_spanned(
&input.id_var,
format!("Block name '{}' not found in registry", block_name),
)
.to_compile_error()
.into();
}
let mut arms = Vec::new();
for (id, _) in filtered_names {
arms.push(quote! {
#block_state_id_var == BlockStateId(#id)
});
}
let joined = quote! {
#(#arms)||*

let states = states.unwrap().iter().map(|&x| x as u32);

let matched = quote! {
match #block_id_var {
BlockStateId(#(#states)|*) => true,
_ => false
}
};
joined.into()
matched.into()
}
Loading
Loading