diff --git a/Cargo.lock b/Cargo.lock index 6822eebf9..17592153e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -348,9 +348,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.61" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "jobserver", @@ -1534,9 +1534,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ "foldhash 0.2.0", "serde", @@ -1867,7 +1867,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -2407,7 +2407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" dependencies = [ "crc32fast", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "indexmap", "memchr", ] @@ -3028,6 +3028,7 @@ dependencies = [ name = "pumpkin-world" version = "0.1.0-dev+26.1" dependencies = [ + "arc-swap", "bitflags", "bytes", "criterion", @@ -3186,7 +3187,7 @@ checksum = "de2c52737737f8609e94f975dee22854a2d5c125772d4b1cf292120f4d45c186" dependencies = [ "allocator-api2", "bumpalo", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "log", "rustc-hash", "smallvec", @@ -3904,9 +3905,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.52.2" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "110a78583f19d5cdb2c5ccf321d1290344e71313c6c37d43520d386027d18386" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -4516,7 +4517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e6fb4c2bee46c5ea4d40f8cdb5c131725cd976718ec56f1c8e82fbde5fa2a80" dependencies = [ "bitflags", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "indexmap", "semver", ] @@ -4528,7 +4529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4439c5eee9df71ee0c6efb37f63b1fcb1fec38f85f5142c54e7ed05d33091a" dependencies = [ "bitflags", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "indexmap", "semver", "serde", @@ -5408,7 +5409,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ffe4064318cdf3c08cb99343b44c039fcefe61ccdf58aa9975285f13d74d1fc" dependencies = [ "anyhow", - "hashbrown 0.17.0", + "hashbrown 0.17.1", "id-arena", "indexmap", "log", diff --git a/pumpkin-world/Cargo.toml b/pumpkin-world/Cargo.toml index 2785ed6d2..2edc291b7 100644 --- a/pumpkin-world/Cargo.toml +++ b/pumpkin-world/Cargo.toml @@ -34,6 +34,7 @@ crossbeam.workspace = true sha2.workspace = true bitflags.workspace = true +arc-swap.workspace = true dashmap.workspace = true diff --git a/pumpkin-world/benches/chunk_gen.rs b/pumpkin-world/benches/chunk_gen.rs index 2906bf839..ce36cd7e2 100644 --- a/pumpkin-world/benches/chunk_gen.rs +++ b/pumpkin-world/benches/chunk_gen.rs @@ -4,7 +4,7 @@ use pumpkin_util::world_seed::Seed; use pumpkin_world::biome::hash_seed; use pumpkin_world::chunk_system::{StagedChunkEnum, generate_single_chunk}; use pumpkin_world::generation::get_world_gen; -use pumpkin_world::world::BlockRegistryExt; +use pumpkin_world::world::WorldPortalExt; use std::hint::black_box; use std::sync::Arc; @@ -32,7 +32,7 @@ fn bench_full_chunk_generation(c: &mut Criterion) { } struct BlockRegistry; -impl BlockRegistryExt for BlockRegistry { +impl WorldPortalExt for BlockRegistry { fn can_place_at( &self, _block: &pumpkin_data::Block, @@ -42,6 +42,15 @@ impl BlockRegistryExt for BlockRegistry { ) -> bool { true } + + fn spawn_mobs_for_chunk_generation( + &self, + _cache: &mut dyn pumpkin_world::generation::proto_chunk::GenerationCache, + _biome: &'static pumpkin_data::chunk::Biome, + _chunk_x: i32, + _chunk_z: i32, + ) { + } } criterion_group!(benches, bench_full_chunk_generation,); diff --git a/pumpkin-world/src/chunk_system/chunk_loading.rs b/pumpkin-world/src/chunk_system/chunk_loading.rs index 9150c86d4..e4da1cbac 100644 --- a/pumpkin-world/src/chunk_system/chunk_loading.rs +++ b/pumpkin-world/src/chunk_system/chunk_loading.rs @@ -129,7 +129,7 @@ pub struct ChunkLoading { impl ChunkLoading { // pub const FULL_CHUNK_LEVEL: i8 = 33; pub const FULL_CHUNK_LEVEL: i8 = 43; - pub const MAX_LEVEL: i8 = 48; // level 48 will be unloaded. + pub const MAX_LEVEL: i8 = 49; // level 49 will be unloaded. fn debug_check_error(&self) -> bool { let mut temp = ChunkLevel::default(); for (ticket_pos, levels) in &self.ticket { diff --git a/pumpkin-world/src/chunk_system/chunk_state.rs b/pumpkin-world/src/chunk_system/chunk_state.rs index 57b02b74d..c995554af 100644 --- a/pumpkin-world/src/chunk_system/chunk_state.rs +++ b/pumpkin-world/src/chunk_system/chunk_state.rs @@ -29,9 +29,11 @@ pub enum StagedChunkEnum { /// Chunk with carvers applied, ready for features and structures Carvers, /// Chunk with features and structures, ready for lighting - Features, // FEATURES SPAWN - /// Chunk with lighting calculated, ready for finalization + Features, // FEATURES + /// Chunk with lighting calculated, ready for spawning Lighting, // INITIALIZE LIGHT + /// Chunk with mobs spawned, ready for finalization + Spawn, // SPAWN /// Fully generated chunk Full, } @@ -48,7 +50,8 @@ impl From for StagedChunkEnum { 7 => Self::Carvers, 8 => Self::Features, 9 => Self::Lighting, - 10 => Self::Full, + 10 => Self::Spawn, + 11 => Self::Full, _ => panic!(), } } @@ -65,9 +68,9 @@ impl From for StagedChunkEnum { ChunkStatus::Surface => Self::Surface, ChunkStatus::Carvers => Self::Carvers, ChunkStatus::Features => Self::Features, - ChunkStatus::Spawn => Self::Features, ChunkStatus::InitializeLight => Self::Lighting, ChunkStatus::Light => Self::Lighting, + ChunkStatus::Spawn => Self::Spawn, ChunkStatus::Full => Self::Full, } } @@ -85,6 +88,7 @@ impl From for ChunkStatus { StagedChunkEnum::Carvers => Self::Carvers, StagedChunkEnum::Features => Self::Features, StagedChunkEnum::Lighting => Self::Light, + StagedChunkEnum::Spawn => Self::Spawn, StagedChunkEnum::Full => Self::Full, _ => panic!(), } @@ -97,22 +101,25 @@ impl StagedChunkEnum { if level <= 43 { Self::Full } else if level <= 44 { - Self::Lighting + Self::Spawn } else if level <= 45 { - Self::Features + Self::Lighting } else if level <= 46 { - Self::Carvers + Self::Features } else if level <= 47 { + Self::Carvers + } else if level <= 48 { Self::Surface } else { Self::None } } - /// Total number of state values (0 = None … 10 = Full). + /// Total number of state values (0 = None … 11 = Full). pub const COUNT: usize = Self::Full as usize + 1; pub const FULL_DEPENDENCIES: &'static [Self] = &[ Self::Full, + Self::Spawn, Self::Lighting, Self::Features, Self::Carvers, @@ -132,6 +139,7 @@ impl StagedChunkEnum { Self::Carvers => 0, Self::Features => 1, Self::Lighting => 1, + Self::Spawn => 1, Self::Full => 1, _ => panic!(), } @@ -149,6 +157,7 @@ impl StagedChunkEnum { Self::Carvers => 0, Self::Features => 1, Self::Lighting => 1, + Self::Spawn => 1, Self::Full => 0, _ => panic!(), } @@ -176,7 +185,8 @@ impl StagedChunkEnum { Self::Carvers => &[Self::Surface], Self::Features => &[Self::Carvers, Self::Carvers], Self::Lighting => &[Self::Features, Self::Features], - Self::Full => &[Self::Lighting, Self::Lighting], + Self::Spawn => &[Self::Lighting, Self::Lighting], + Self::Full => &[Self::Spawn, Self::Spawn], _ => panic!(), } } diff --git a/pumpkin-world/src/chunk_system/generation.rs b/pumpkin-world/src/chunk_system/generation.rs index 52d061711..af99efe17 100644 --- a/pumpkin-world/src/chunk_system/generation.rs +++ b/pumpkin-world/src/chunk_system/generation.rs @@ -2,7 +2,7 @@ use pumpkin_data::dimension::Dimension; use crate::ProtoChunk; use crate::generation::generator::VanillaGenerator; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; use pumpkin_config::lighting::LightingEngineConfig; use super::{Cache, Chunk, StagedChunkEnum}; @@ -11,7 +11,7 @@ pub fn generate_single_chunk( _dimension: &Dimension, _biome_mixer_seed: i64, generator: &VanillaGenerator, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk_x: i32, chunk_z: i32, target_stage: StagedChunkEnum, @@ -39,6 +39,7 @@ pub fn generate_single_chunk( StagedChunkEnum::Surface, StagedChunkEnum::Features, StagedChunkEnum::Lighting, + StagedChunkEnum::Spawn, StagedChunkEnum::Full, ]; @@ -64,13 +65,13 @@ mod tests { use crate::biome::hash_seed; use crate::chunk_system::{StagedChunkEnum, generate_single_chunk}; use crate::generation::get_world_gen; - use crate::world::BlockRegistryExt; + use crate::world::WorldPortalExt; use pumpkin_data::dimension::Dimension; use pumpkin_util::world_seed::Seed; use std::sync::Arc; struct BlockRegistry; - impl BlockRegistryExt for BlockRegistry { + impl WorldPortalExt for BlockRegistry { fn can_place_at( &self, _block: &pumpkin_data::Block, @@ -80,6 +81,15 @@ mod tests { ) -> bool { true } + + fn spawn_mobs_for_chunk_generation( + &self, + _cache: &mut dyn crate::generation::proto_chunk::GenerationCache, + _biome: &'static pumpkin_data::chunk::Biome, + _chunk_x: i32, + _chunk_z: i32, + ) { + } } #[test] diff --git a/pumpkin-world/src/chunk_system/generation_cache.rs b/pumpkin-world/src/chunk_system/generation_cache.rs index 15e1851f6..3bfd58868 100644 --- a/pumpkin-world/src/chunk_system/generation_cache.rs +++ b/pumpkin-world/src/chunk_system/generation_cache.rs @@ -4,7 +4,7 @@ use crate::chunk::ChunkHeightmapType; use crate::generation::generator; use crate::generation::height_limit::HeightLimitView; use crate::generation::proto_chunk::GenerationCache; -use crate::world::{BlockAccessor, BlockRegistryExt}; +use crate::world::{BlockAccessor, WorldPortalExt}; use crate::{BlockStateId, ProtoChunk}; use pumpkin_config::lighting::LightingEngineConfig; use pumpkin_data::biome::Biome; @@ -360,7 +360,7 @@ impl Cache { &mut self, stage: StagedChunkEnum, generator: &generator::VanillaGenerator, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, lighting_config: &LightingEngineConfig, ) { let mid = ((self.size * self.size) >> 1) as usize; @@ -407,9 +407,12 @@ impl Cache { // Engine's internal state is cleared by initialize_light() and will be dropped here drop(engine); } + StagedChunkEnum::Spawn => { + ProtoChunk::spawn_mobs(self, block_registry); + } StagedChunkEnum::Full => { let chunk = self.chunks[mid].get_proto_chunk_mut(); - debug_assert_eq!(chunk.stage, StagedChunkEnum::Lighting); + debug_assert_eq!(chunk.stage, StagedChunkEnum::Spawn); chunk.stage = StagedChunkEnum::Full; self.chunks[mid].upgrade_to_level_chunk(&generator.dimension, lighting_config); } diff --git a/pumpkin-world/src/chunk_system/schedule.rs b/pumpkin-world/src/chunk_system/schedule.rs index 327c1f3f6..446cea71c 100644 --- a/pumpkin-world/src/chunk_system/schedule.rs +++ b/pumpkin-world/src/chunk_system/schedule.rs @@ -721,14 +721,14 @@ impl GenerationSchedule { Chunk::Level(chunk) => { let mut holder = self.chunk_map.remove(&new_pos).unwrap(); if new_pos == pos { - if holder.current_stage != StagedChunkEnum::Lighting { + if holder.current_stage != StagedChunkEnum::Spawn { warn!( "receive_chunk(Level): holder at {:?} for pos {:?} expected {:?}; aligning", holder.current_stage, new_pos, - StagedChunkEnum::Lighting + StagedChunkEnum::Spawn ); - holder.current_stage = StagedChunkEnum::Lighting; + holder.current_stage = StagedChunkEnum::Spawn; } self.drop_node(holder.tasks[StagedChunkEnum::Full as usize]); holder.tasks[StagedChunkEnum::Full as usize] = NodeKey::null(); diff --git a/pumpkin-world/src/chunk_system/worker_logic.rs b/pumpkin-world/src/chunk_system/worker_logic.rs index 73652a612..e2b054df2 100644 --- a/pumpkin-world/src/chunk_system/worker_logic.rs +++ b/pumpkin-world/src/chunk_system/worker_logic.rs @@ -229,14 +229,11 @@ pub fn run_generation( level: &Level, _settings: &GenerationSettings, ) -> RecvChunk { + let portal = level.world_portal.load_full(); + let portal_ref = portal.as_deref().expect("Portal should be initialized"); // Run generation with panic catching let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - cache.advance( - stage, - &level.world_gen, - level.block_registry.as_ref(), - &level.lighting_config, - ); + cache.advance(stage, &level.world_gen, portal_ref, &level.lighting_config); cache // Return cache on success })); diff --git a/pumpkin-world/src/dimension.rs b/pumpkin-world/src/dimension.rs index 99f5bd8aa..23023df89 100644 --- a/pumpkin-world/src/dimension.rs +++ b/pumpkin-world/src/dimension.rs @@ -3,13 +3,12 @@ use std::{path::PathBuf, sync::Arc}; use pumpkin_config::world::LevelConfig; use pumpkin_data::dimension::Dimension; -use crate::{level::Level, world::BlockRegistryExt}; +use crate::level::Level; pub fn into_level( dimension: Dimension, level_config: &LevelConfig, mut base_directory: PathBuf, - block_registry: Arc, seed: i64, gen_pool: Option>, ) -> Arc { @@ -19,12 +18,5 @@ pub fn into_level( } else if dimension == Dimension::THE_END { base_directory.push("DIM1"); } - Level::from_root_folder( - level_config, - base_directory, - block_registry, - seed, - dimension, - gen_pool, - ) + Level::from_root_folder(level_config, base_directory, seed, dimension, gen_pool) } diff --git a/pumpkin-world/src/generation/block_predicate.rs b/pumpkin-world/src/generation/block_predicate.rs index 7bef05863..ad78066a2 100644 --- a/pumpkin-world/src/generation/block_predicate.rs +++ b/pumpkin-world/src/generation/block_predicate.rs @@ -6,7 +6,7 @@ use pumpkin_util::math::{position::BlockPos, vector3::Vector3}; use crate::block::RawBlockState; use crate::generation::proto_chunk::GenerationCache; -use crate::{block::BlockStateCodec, world::BlockRegistryExt}; +use crate::{block::BlockStateCodec, world::WorldPortalExt}; pub enum BlockPredicate { MatchingBlocks(MatchingBlocksBlockPredicate), @@ -28,7 +28,7 @@ pub enum BlockPredicate { impl BlockPredicate { pub fn test( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &T, pos: &BlockPos, ) -> bool { @@ -131,7 +131,7 @@ pub struct AnyOfBlockPredicate { impl AnyOfBlockPredicate { pub fn test( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &T, pos: &BlockPos, ) -> bool { @@ -152,7 +152,7 @@ pub struct AllOfBlockPredicate { impl AllOfBlockPredicate { pub fn test( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &T, pos: &BlockPos, ) -> bool { @@ -173,7 +173,7 @@ pub struct NotBlockPredicate { impl NotBlockPredicate { pub fn test( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &T, pos: &BlockPos, ) -> bool { @@ -200,7 +200,7 @@ pub struct WouldSurviveBlockPredicate { impl WouldSurviveBlockPredicate { pub fn test( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &T, pos: &BlockPos, ) -> bool { diff --git a/pumpkin-world/src/generation/block_state_provider.rs b/pumpkin-world/src/generation/block_state_provider.rs index 10e72c495..0bc87d4e6 100644 --- a/pumpkin-world/src/generation/block_state_provider.rs +++ b/pumpkin-world/src/generation/block_state_provider.rs @@ -13,7 +13,7 @@ use pumpkin_util::{ use super::noise::perlin::DoublePerlinNoiseSampler; use crate::generation::block_predicate::BlockPredicate; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub enum BlockStateProvider { Simple(SimpleStateProvider), @@ -43,7 +43,7 @@ impl BlockStateProvider { pub fn get_with_context( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &T, random: &mut RandomGenerator, pos: BlockPos, @@ -56,7 +56,7 @@ impl BlockStateProvider { pub fn get_optional( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &T, random: &mut RandomGenerator, pos: BlockPos, @@ -76,7 +76,7 @@ pub struct RuleBasedBlockStateProvider { impl RuleBasedBlockStateProvider { pub fn get( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &T, random: &mut RandomGenerator, pos: BlockPos, @@ -88,7 +88,7 @@ impl RuleBasedBlockStateProvider { } pub fn get_optional( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &T, random: &mut RandomGenerator, pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/configured_features.rs b/pumpkin-world/src/generation/feature/configured_features.rs index bb98839e8..193eca730 100644 --- a/pumpkin-world/src/generation/feature/configured_features.rs +++ b/pumpkin-world/src/generation/feature/configured_features.rs @@ -69,7 +69,7 @@ use super::features::{ weeping_vines::WeepingVinesFeature, }; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub static CONFIGURED_FEATURES: LazyLock> = LazyLock::new(build_configured_features); @@ -147,7 +147,7 @@ impl ConfiguredFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature_name: &str, // This placed feature diff --git a/pumpkin-world/src/generation/feature/features/bamboo.rs b/pumpkin-world/src/generation/feature/features/bamboo.rs index e8418e79d..8a8aa2367 100644 --- a/pumpkin-world/src/generation/feature/features/bamboo.rs +++ b/pumpkin-world/src/generation/feature/features/bamboo.rs @@ -9,7 +9,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct BambooFeature { pub probability: f32, @@ -20,7 +20,7 @@ impl BambooFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature: &str, // This placed feature diff --git a/pumpkin-world/src/generation/feature/features/basalt_columns.rs b/pumpkin-world/src/generation/feature/features/basalt_columns.rs index e81e1b7f6..a8fe0b613 100644 --- a/pumpkin-world/src/generation/feature/features/basalt_columns.rs +++ b/pumpkin-world/src/generation/feature/features/basalt_columns.rs @@ -4,7 +4,7 @@ use pumpkin_util::{ random::{RandomGenerator, RandomImpl}, }; -use crate::{generation::proto_chunk::GenerationCache, world::BlockRegistryExt}; +use crate::{generation::proto_chunk::GenerationCache, world::WorldPortalExt}; const LAVA_SEA_LEVEL: i32 = 32; // TODO: use getSeaLevel() instead of hardcoding this const CLUSTERED_REACH: i32 = 5; @@ -22,7 +22,7 @@ impl BasaltColumnsFeature { pub fn generate( &self, chunk: &mut T, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _min_y: i8, _height_limit: u16, _feature: &str, diff --git a/pumpkin-world/src/generation/feature/features/block_column.rs b/pumpkin-world/src/generation/feature/features/block_column.rs index e095abb53..d8d076de2 100644 --- a/pumpkin-world/src/generation/feature/features/block_column.rs +++ b/pumpkin-world/src/generation/feature/features/block_column.rs @@ -7,7 +7,7 @@ use pumpkin_util::{ use crate::generation::proto_chunk::GenerationCache; use crate::{ generation::{block_predicate::BlockPredicate, block_state_provider::BlockStateProvider}, - world::BlockRegistryExt, + world::WorldPortalExt, }; pub struct BlockColumnFeature { @@ -27,7 +27,7 @@ impl BlockColumnFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature: &str, // This placed feature diff --git a/pumpkin-world/src/generation/feature/features/disk.rs b/pumpkin-world/src/generation/feature/features/disk.rs index 0dc1ae69c..4a0bb289c 100644 --- a/pumpkin-world/src/generation/feature/features/disk.rs +++ b/pumpkin-world/src/generation/feature/features/disk.rs @@ -5,7 +5,7 @@ use crate::generation::{ block_predicate::BlockPredicate, block_state_provider::BlockStateProvider, proto_chunk::GenerationCache, }; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct DiskFeature { pub state_provider: BlockStateProvider, @@ -19,7 +19,7 @@ impl DiskFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature: &str, @@ -55,7 +55,7 @@ impl DiskFeature { fn place_column( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, random: &mut RandomGenerator, top: i32, bottom: i32, diff --git a/pumpkin-world/src/generation/feature/features/end_platform.rs b/pumpkin-world/src/generation/feature/features/end_platform.rs index acdb5803e..0d774933f 100644 --- a/pumpkin-world/src/generation/feature/features/end_platform.rs +++ b/pumpkin-world/src/generation/feature/features/end_platform.rs @@ -5,7 +5,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct EndPlatformFeature; @@ -14,7 +14,7 @@ impl EndPlatformFeature { pub fn generate( &self, chunk: &mut T, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature: &str, // This placed feature diff --git a/pumpkin-world/src/generation/feature/features/end_spike.rs b/pumpkin-world/src/generation/feature/features/end_spike.rs index db5887904..1e5e640c4 100644 --- a/pumpkin-world/src/generation/feature/features/end_spike.rs +++ b/pumpkin-world/src/generation/feature/features/end_spike.rs @@ -8,7 +8,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::{generation::section_coords, world::BlockRegistryExt}; +use crate::{generation::section_coords, world::WorldPortalExt}; pub struct EndSpikeFeature { pub crystal_invulnerable: bool, @@ -37,7 +37,7 @@ impl EndSpikeFeature { pub fn generate( &self, chunk: &mut T, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature: &str, // This placed feature diff --git a/pumpkin-world/src/generation/feature/features/geode.rs b/pumpkin-world/src/generation/feature/features/geode.rs index ca40c4f9d..afb1de243 100644 --- a/pumpkin-world/src/generation/feature/features/geode.rs +++ b/pumpkin-world/src/generation/feature/features/geode.rs @@ -9,7 +9,7 @@ use pumpkin_util::{ use crate::generation::feature::features::spring_feature::BlockWrapper; use crate::{ - block::BlockStateCodec, generation::proto_chunk::GenerationCache, world::BlockRegistryExt, + block::BlockStateCodec, generation::proto_chunk::GenerationCache, world::WorldPortalExt, }; use pumpkin_util::random::RandomImpl; use std::cmp::Ordering; @@ -102,7 +102,7 @@ impl GeodeFeature { pub fn generate( &self, chunk: &mut T, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature_name: &str, diff --git a/pumpkin-world/src/generation/feature/features/lake.rs b/pumpkin-world/src/generation/feature/features/lake.rs index 947b6afe3..5fdd2dff3 100644 --- a/pumpkin-world/src/generation/feature/features/lake.rs +++ b/pumpkin-world/src/generation/feature/features/lake.rs @@ -5,7 +5,7 @@ use pumpkin_util::{ }; use crate::generation::{block_state_provider::BlockStateProvider, proto_chunk::GenerationCache}; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct LakeFeature { pub fluid: BlockStateProvider, @@ -15,7 +15,7 @@ pub struct LakeFeature { impl LakeFeature { pub fn generate( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &mut T, random: &mut RandomGenerator, pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/nether_forest_vegetation.rs b/pumpkin-world/src/generation/feature/features/nether_forest_vegetation.rs index fb5f82d1a..4c9c3eaee 100644 --- a/pumpkin-world/src/generation/feature/features/nether_forest_vegetation.rs +++ b/pumpkin-world/src/generation/feature/features/nether_forest_vegetation.rs @@ -5,7 +5,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::{generation::block_state_provider::BlockStateProvider, world::BlockRegistryExt}; +use crate::{generation::block_state_provider::BlockStateProvider, world::WorldPortalExt}; pub struct NetherForestVegetationFeature { pub state_provider: BlockStateProvider, @@ -18,7 +18,7 @@ impl NetherForestVegetationFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature: &str, diff --git a/pumpkin-world/src/generation/feature/features/netherrack_replace_blobs.rs b/pumpkin-world/src/generation/feature/features/netherrack_replace_blobs.rs index f05aa8f44..3304f7879 100644 --- a/pumpkin-world/src/generation/feature/features/netherrack_replace_blobs.rs +++ b/pumpkin-world/src/generation/feature/features/netherrack_replace_blobs.rs @@ -5,7 +5,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct ReplaceBlobsFeature { pub target: &'static BlockState, @@ -18,7 +18,7 @@ impl ReplaceBlobsFeature { pub fn generate( &self, chunk: &mut T, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature: &str, // This placed feature diff --git a/pumpkin-world/src/generation/feature/features/ore.rs b/pumpkin-world/src/generation/feature/features/ore.rs index 4e3f9494f..4ca6172a7 100644 --- a/pumpkin-world/src/generation/feature/features/ore.rs +++ b/pumpkin-world/src/generation/feature/features/ore.rs @@ -7,7 +7,7 @@ use pumpkin_util::{ }; use crate::{block::RawBlockState, generation::proto_chunk::GenerationCache}; -use crate::{generation::rule::RuleTest, world::BlockRegistryExt}; +use crate::{generation::rule::RuleTest, world::WorldPortalExt}; pub struct OreFeature { pub size: i32, @@ -25,7 +25,7 @@ impl OreFeature { pub fn generate( &self, chunk: &mut T, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature: &str, // This placed feature diff --git a/pumpkin-world/src/generation/feature/features/random_boolean_selector.rs b/pumpkin-world/src/generation/feature/features/random_boolean_selector.rs index ca44a6a3c..0415d248c 100644 --- a/pumpkin-world/src/generation/feature/features/random_boolean_selector.rs +++ b/pumpkin-world/src/generation/feature/features/random_boolean_selector.rs @@ -4,7 +4,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::{generation::feature::placed_features::PlacedFeatureWrapper, world::BlockRegistryExt}; +use crate::{generation::feature::placed_features::PlacedFeatureWrapper, world::WorldPortalExt}; pub struct RandomBooleanFeature { pub feature_true: Box, @@ -16,7 +16,7 @@ impl RandomBooleanFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature_name: &str, // This placed feature diff --git a/pumpkin-world/src/generation/feature/features/random_patch.rs b/pumpkin-world/src/generation/feature/features/random_patch.rs index d33d8cac9..9d417a2fc 100644 --- a/pumpkin-world/src/generation/feature/features/random_patch.rs +++ b/pumpkin-world/src/generation/feature/features/random_patch.rs @@ -4,7 +4,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::{generation::feature::placed_features::PlacedFeature, world::BlockRegistryExt}; +use crate::{generation::feature::placed_features::PlacedFeature, world::WorldPortalExt}; pub struct RandomPatchFeature { pub tries: u8, @@ -18,7 +18,7 @@ impl RandomPatchFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature: &str, diff --git a/pumpkin-world/src/generation/feature/features/random_selector.rs b/pumpkin-world/src/generation/feature/features/random_selector.rs index 8cdd4cdc0..2600bfa81 100644 --- a/pumpkin-world/src/generation/feature/features/random_selector.rs +++ b/pumpkin-world/src/generation/feature/features/random_selector.rs @@ -4,7 +4,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::{generation::feature::placed_features::PlacedFeatureWrapper, world::BlockRegistryExt}; +use crate::{generation::feature::placed_features::PlacedFeatureWrapper, world::WorldPortalExt}; pub struct RandomFeature { pub features: Vec, @@ -21,7 +21,7 @@ impl RandomFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature_name: &str, // This placed feature diff --git a/pumpkin-world/src/generation/feature/features/root_system.rs b/pumpkin-world/src/generation/feature/features/root_system.rs index 76a1fdd9b..6f3d70c00 100644 --- a/pumpkin-world/src/generation/feature/features/root_system.rs +++ b/pumpkin-world/src/generation/feature/features/root_system.rs @@ -6,7 +6,7 @@ use pumpkin_util::{ use crate::generation::block_predicate::BlockPredicate; use crate::generation::block_state_provider::BlockStateProvider; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct RootSystemFeature { pub feature: Box, @@ -29,7 +29,7 @@ impl RootSystemFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature_name: &str, @@ -87,7 +87,7 @@ impl RootSystemFeature { fn place_roots( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, random: &mut RandomGenerator, pos: BlockPos, ) { @@ -98,7 +98,7 @@ impl RootSystemFeature { fn place_rooted_dirt( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, random: &mut RandomGenerator, pos: BlockPos, ) { @@ -151,7 +151,7 @@ impl RootSystemFeature { fn place_hanging_roots( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, random: &mut RandomGenerator, pos: BlockPos, ) { diff --git a/pumpkin-world/src/generation/feature/features/scattered_ore.rs b/pumpkin-world/src/generation/feature/features/scattered_ore.rs index f0f7f0d44..22c5afe8c 100644 --- a/pumpkin-world/src/generation/feature/features/scattered_ore.rs +++ b/pumpkin-world/src/generation/feature/features/scattered_ore.rs @@ -4,7 +4,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; use super::ore::{OreFeature, OreTarget}; @@ -19,7 +19,7 @@ impl ScatteredOreFeature { pub fn generate( &self, chunk: &mut T, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature: &str, diff --git a/pumpkin-world/src/generation/feature/features/sculk_patch.rs b/pumpkin-world/src/generation/feature/features/sculk_patch.rs index d2b27ae35..d05595ab7 100644 --- a/pumpkin-world/src/generation/feature/features/sculk_patch.rs +++ b/pumpkin-world/src/generation/feature/features/sculk_patch.rs @@ -6,7 +6,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct SculkPatchFeature { pub charge_count: i32, @@ -21,7 +21,7 @@ pub struct SculkPatchFeature { impl SculkPatchFeature { pub fn generate( &self, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, chunk: &mut T, random: &mut RandomGenerator, pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/simple_block.rs b/pumpkin-world/src/generation/feature/features/simple_block.rs index e0e1391dc..47b5c7b59 100644 --- a/pumpkin-world/src/generation/feature/features/simple_block.rs +++ b/pumpkin-world/src/generation/feature/features/simple_block.rs @@ -4,7 +4,7 @@ use pumpkin_util::{math::position::BlockPos, random::RandomGenerator}; use crate::generation::proto_chunk::GenerationCache; use crate::{ generation::block_state_provider::BlockStateProvider, - world::{BlockAccessor, BlockRegistryExt}, + world::{BlockAccessor, WorldPortalExt}, }; pub struct SimpleBlockFeature { @@ -15,7 +15,7 @@ pub struct SimpleBlockFeature { impl SimpleBlockFeature { pub fn generate( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &mut T, random: &mut RandomGenerator, pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/simple_random_selector.rs b/pumpkin-world/src/generation/feature/features/simple_random_selector.rs index 6756a8480..80d878a3e 100644 --- a/pumpkin-world/src/generation/feature/features/simple_random_selector.rs +++ b/pumpkin-world/src/generation/feature/features/simple_random_selector.rs @@ -4,7 +4,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::{generation::feature::placed_features::PlacedFeature, world::BlockRegistryExt}; +use crate::{generation::feature::placed_features::PlacedFeature, world::WorldPortalExt}; pub struct SimpleRandomFeature { pub features: Vec, @@ -15,7 +15,7 @@ impl SimpleRandomFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature_name: &str, // This placed feature diff --git a/pumpkin-world/src/generation/feature/features/spring_feature.rs b/pumpkin-world/src/generation/feature/features/spring_feature.rs index 67143a996..e61044ff3 100644 --- a/pumpkin-world/src/generation/feature/features/spring_feature.rs +++ b/pumpkin-world/src/generation/feature/features/spring_feature.rs @@ -2,7 +2,7 @@ use pumpkin_data::{BlockDirection, BlockState}; use pumpkin_util::{math::position::BlockPos, random::RandomGenerator}; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct SpringFeatureFeature { pub state: &'static BlockState, @@ -30,7 +30,7 @@ impl BlockWrapper { impl SpringFeatureFeature { pub fn generate( &self, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, chunk: &mut T, _random: &mut RandomGenerator, pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/tree/mod.rs b/pumpkin-world/src/generation/feature/features/tree/mod.rs index bf96ff48b..e42e9fd1b 100644 --- a/pumpkin-world/src/generation/feature/features/tree/mod.rs +++ b/pumpkin-world/src/generation/feature/features/tree/mod.rs @@ -8,7 +8,7 @@ use trunk::TrunkPlacer; use crate::generation::proto_chunk::GenerationCache; use crate::generation::{block_state_provider::BlockStateProvider, feature::size::FeatureSize}; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub mod decorator; pub mod foliage; @@ -35,7 +35,7 @@ impl TreeFeature { #[expect(clippy::too_many_arguments)] pub fn generate( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &mut T, min_y: i8, height: u16, @@ -78,7 +78,7 @@ impl TreeFeature { #[expect(clippy::too_many_arguments)] fn generate_main( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &mut T, _min_y: i8, _height: u16, diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/bending.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/bending.rs index ce6469ea8..b01461b23 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/bending.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/bending.rs @@ -10,7 +10,7 @@ use crate::{ block_state_provider::BlockStateProvider, feature::features::tree::{TreeNode, trunk::TrunkPlacer}, }, - world::BlockRegistryExt, + world::WorldPortalExt, }; pub struct BendingTrunkPlacer { @@ -22,7 +22,7 @@ impl BendingTrunkPlacer { #[expect(clippy::too_many_arguments)] pub fn generate( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, placer: &TrunkPlacer, height: u32, start_pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/cherry.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/cherry.rs index fd91d01c2..e93114b2d 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/cherry.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/cherry.rs @@ -7,7 +7,7 @@ use super::TrunkPlacer; use crate::generation::block_state_provider::BlockStateProvider; use crate::generation::feature::features::tree::TreeNode; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; use pumpkin_data::block_properties::Axis; pub struct CherryTrunkPlacer { @@ -21,7 +21,7 @@ impl CherryTrunkPlacer { #[expect(clippy::too_many_arguments)] pub fn generate( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, placer: &TrunkPlacer, height: u32, start_pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/dark_oak.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/dark_oak.rs index 75bd8a394..83ffb7bfa 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/dark_oak.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/dark_oak.rs @@ -10,7 +10,7 @@ use crate::{ block_state_provider::BlockStateProvider, feature::features::tree::{TreeFeature, TreeNode, trunk::TrunkPlacer}, }, - world::BlockRegistryExt, + world::WorldPortalExt, }; pub struct DarkOakTrunkPlacer; @@ -18,7 +18,7 @@ pub struct DarkOakTrunkPlacer; impl DarkOakTrunkPlacer { #[expect(clippy::too_many_arguments)] pub fn generate( - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, placer: &TrunkPlacer, height: u32, start_pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/fancy.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/fancy.rs index c0eb50ef8..8c409ff8a 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/fancy.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/fancy.rs @@ -16,7 +16,7 @@ use crate::{ block_state_provider::BlockStateProvider, feature::features::tree::{TreeFeature, TreeNode}, }, - world::BlockRegistryExt, + world::WorldPortalExt, }; pub struct FancyTrunkPlacer; @@ -24,7 +24,7 @@ pub struct FancyTrunkPlacer; impl FancyTrunkPlacer { #[expect(clippy::too_many_arguments)] pub fn generate( - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, placer: &TrunkPlacer, height: u32, start_pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/forking.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/forking.rs index 8846f0077..c1dbdc681 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/forking.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/forking.rs @@ -6,7 +6,7 @@ use super::TrunkPlacer; use crate::generation::block_state_provider::BlockStateProvider; use crate::generation::feature::features::tree::TreeNode; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; use pumpkin_data::BlockDirection; pub struct ForkingTrunkPlacer; @@ -14,7 +14,7 @@ pub struct ForkingTrunkPlacer; impl ForkingTrunkPlacer { #[expect(clippy::too_many_arguments)] pub fn generate( - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, placer: &TrunkPlacer, height: u32, start_pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/giant.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/giant.rs index 500c13f71..3ef9eafa2 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/giant.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/giant.rs @@ -7,7 +7,7 @@ use crate::{ block_state_provider::BlockStateProvider, feature::features::tree::{TreeNode, trunk::TrunkPlacer}, }, - world::BlockRegistryExt, + world::WorldPortalExt, }; pub struct GiantTrunkPlacer; @@ -15,7 +15,7 @@ pub struct GiantTrunkPlacer; impl GiantTrunkPlacer { #[expect(clippy::too_many_arguments)] pub fn generate( - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, placer: &TrunkPlacer, height: u32, start_pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/mega_jungle.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/mega_jungle.rs index 97c602347..ba37230b0 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/mega_jungle.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/mega_jungle.rs @@ -15,7 +15,7 @@ use crate::{ trunk::{TrunkPlacer, giant::GiantTrunkPlacer}, }, }, - world::BlockRegistryExt, + world::WorldPortalExt, }; pub struct MegaJungleTrunkPlacer; @@ -23,7 +23,7 @@ pub struct MegaJungleTrunkPlacer; impl MegaJungleTrunkPlacer { #[expect(clippy::too_many_arguments)] pub fn generate( - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, placer: &TrunkPlacer, height: u32, start_pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/mod.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/mod.rs index 3b8dd6355..fdd39c8c1 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/mod.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/mod.rs @@ -15,7 +15,7 @@ use crate::generation::feature::features::tree::trunk::{ upwards_branching::UpwardsBranchingTrunkPlacer, }; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub mod bending; pub mod cherry; @@ -43,7 +43,7 @@ impl TrunkPlacer { pub fn set_dirt( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &mut T, random: &mut RandomGenerator, pos: &BlockPos, @@ -85,7 +85,7 @@ impl TrunkPlacer { #[expect(clippy::too_many_arguments)] pub fn generate( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, height: u32, start_pos: BlockPos, chunk: &mut T, @@ -122,7 +122,7 @@ impl TrunkType { #[expect(clippy::too_many_arguments)] pub fn generate( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, placer: &TrunkPlacer, height: u32, start_pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/straight.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/straight.rs index e15233f2e..c4e719741 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/straight.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/straight.rs @@ -6,14 +6,14 @@ use super::TrunkPlacer; use crate::generation::block_state_provider::BlockStateProvider; use crate::generation::feature::features::tree::TreeNode; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct StraightTrunkPlacer; impl StraightTrunkPlacer { #[expect(clippy::too_many_arguments)] pub fn generate( - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, placer: &TrunkPlacer, height: u32, start_pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/tree/trunk/upwards_branching.rs b/pumpkin-world/src/generation/feature/features/tree/trunk/upwards_branching.rs index e560f329a..75a3dc112 100644 --- a/pumpkin-world/src/generation/feature/features/tree/trunk/upwards_branching.rs +++ b/pumpkin-world/src/generation/feature/features/tree/trunk/upwards_branching.rs @@ -7,7 +7,7 @@ use super::TrunkPlacer; use crate::generation::block_state_provider::BlockStateProvider; use crate::generation::feature::features::tree::{TreeFeature, TreeNode}; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; use pumpkin_data::BlockDirection; pub struct UpwardsBranchingTrunkPlacer { @@ -21,7 +21,7 @@ impl UpwardsBranchingTrunkPlacer { #[expect(clippy::too_many_arguments)] pub fn generate( &self, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, placer: &TrunkPlacer, height: u32, start_pos: BlockPos, diff --git a/pumpkin-world/src/generation/feature/features/vegetation_patch.rs b/pumpkin-world/src/generation/feature/features/vegetation_patch.rs index e2d4a13f7..143b747d5 100644 --- a/pumpkin-world/src/generation/feature/features/vegetation_patch.rs +++ b/pumpkin-world/src/generation/feature/features/vegetation_patch.rs @@ -8,7 +8,7 @@ use pumpkin_util::{ use crate::generation::block_predicate::BlockPredicate; use crate::generation::block_state_provider::BlockStateProvider; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct VegetationPatchFeature { pub replaceable: BlockPredicate, @@ -41,7 +41,7 @@ impl VegetationPatchFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature_name: &str, @@ -79,7 +79,7 @@ impl VegetationPatchFeature { pub(crate) fn place_ground_patch( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, random: &mut RandomGenerator, origin: BlockPos, replaceable: &BlockPredicate, @@ -166,7 +166,7 @@ impl VegetationPatchFeature { fn place_ground( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, replaceable: &BlockPredicate, random: &mut RandomGenerator, mut below_pos: BlockPos, @@ -196,7 +196,7 @@ impl VegetationPatchFeature { pub(crate) fn distribute_vegetation( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, random: &mut RandomGenerator, min_y: i8, height: u16, diff --git a/pumpkin-world/src/generation/feature/features/vines.rs b/pumpkin-world/src/generation/feature/features/vines.rs index 9ab7a6fdf..72be866b5 100644 --- a/pumpkin-world/src/generation/feature/features/vines.rs +++ b/pumpkin-world/src/generation/feature/features/vines.rs @@ -2,7 +2,7 @@ use pumpkin_data::{Block, BlockDirection, BlockState, block_properties::BlockPro use pumpkin_util::{math::position::BlockPos, random::RandomGenerator}; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; pub struct VinesFeature; @@ -11,7 +11,7 @@ impl VinesFeature { pub fn generate( &self, chunk: &mut T, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _min_y: i8, _height: u16, _feature: &str, diff --git a/pumpkin-world/src/generation/feature/features/waterlogged_vegetation_patch.rs b/pumpkin-world/src/generation/feature/features/waterlogged_vegetation_patch.rs index 45c45a9a7..382439ae4 100644 --- a/pumpkin-world/src/generation/feature/features/waterlogged_vegetation_patch.rs +++ b/pumpkin-world/src/generation/feature/features/waterlogged_vegetation_patch.rs @@ -6,7 +6,7 @@ use pumpkin_util::{ }; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; use pumpkin_data::BlockDirection; use super::vegetation_patch::VegetationPatchFeature; @@ -20,7 +20,7 @@ impl WaterloggedVegetationPatchFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature_name: &str, @@ -64,7 +64,7 @@ impl WaterloggedVegetationPatchFeature { fn place_ground_patch( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, random: &mut RandomGenerator, origin: BlockPos, replaceable: &crate::generation::block_predicate::BlockPredicate, @@ -98,7 +98,7 @@ impl WaterloggedVegetationPatchFeature { fn place_vegetation( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature_name: &str, diff --git a/pumpkin-world/src/generation/feature/placed_features.rs b/pumpkin-world/src/generation/feature/placed_features.rs index 98ec8d25f..773642aaf 100644 --- a/pumpkin-world/src/generation/feature/placed_features.rs +++ b/pumpkin-world/src/generation/feature/placed_features.rs @@ -15,7 +15,7 @@ use crate::block::RawBlockState; use crate::generation::block_predicate::BlockPredicate; use crate::generation::height_provider::HeightProvider; use crate::generation::proto_chunk::GenerationCache; -use crate::world::BlockRegistryExt; +use crate::world::WorldPortalExt; use super::configured_features::{CONFIGURED_FEATURES, ConfiguredFeature}; @@ -54,7 +54,7 @@ impl PlacedFeature { pub fn generate( &self, chunk: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature_name: &str, // This placed feature @@ -129,7 +129,7 @@ impl PlacementModifier { pub fn get_positions( &self, chunk: &T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, min_y: i8, height: u16, feature: &str, @@ -213,7 +213,7 @@ impl EnvironmentScanPlacementModifier { pub fn get_positions( &self, chunk: &T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, pos: BlockPos, ) -> Box> { let allowed_search_condition = self @@ -339,7 +339,7 @@ pub struct BlockFilterPlacementModifier { impl ConditionalPlacementModifier for BlockFilterPlacementModifier { fn should_place( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, _feature: &str, chunk: &T, _random: &mut RandomGenerator, @@ -358,7 +358,7 @@ pub struct SurfaceThresholdFilterPlacementModifier { impl ConditionalPlacementModifier for SurfaceThresholdFilterPlacementModifier { fn should_place( &self, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _feature: &str, chunk: &T, _random: &mut RandomGenerator, @@ -378,7 +378,7 @@ pub struct RarityFilterPlacementModifier { impl ConditionalPlacementModifier for RarityFilterPlacementModifier { fn should_place( &self, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _feature: &str, _chunk: &T, random: &mut RandomGenerator, @@ -418,7 +418,7 @@ pub struct SurfaceWaterDepthFilterPlacementModifier { impl ConditionalPlacementModifier for SurfaceWaterDepthFilterPlacementModifier { fn should_place( &self, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, _feature: &str, chunk: &T, _random: &mut RandomGenerator, @@ -435,7 +435,7 @@ pub struct BiomePlacementModifier; impl ConditionalPlacementModifier for BiomePlacementModifier { fn should_place( &self, - _block_registry: &dyn BlockRegistryExt, + _block_registry: &dyn WorldPortalExt, this_feature: &str, chunk: &T, _random: &mut RandomGenerator, @@ -510,7 +510,7 @@ pub trait CountPlacementModifierBase { pub trait ConditionalPlacementModifier { fn get_positions( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, chunk: &T, feature: &str, random: &mut RandomGenerator, @@ -525,7 +525,7 @@ pub trait ConditionalPlacementModifier { fn should_place( &self, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, feature: &str, chunk: &T, random: &mut RandomGenerator, diff --git a/pumpkin-world/src/generation/proto_chunk.rs b/pumpkin-world/src/generation/proto_chunk.rs index c4cae2193..61014c1c1 100644 --- a/pumpkin-world/src/generation/proto_chunk.rs +++ b/pumpkin-world/src/generation/proto_chunk.rs @@ -42,6 +42,7 @@ use crate::generation::noise::perlin::DoublePerlinNoiseSampler; use crate::generation::noise::router::multi_noise_sampler::MultiNoiseSamplerBuilderOptions; use crate::generation::noise::router::surface_height_sampler::SurfaceHeightSamplerBuilderOptions; use crate::generation::noise::{CHUNK_DIM, ChunkNoiseGenerator, LAVA_BLOCK, WATER_BLOCK}; +use crate::generation::section_coords::section_to_block; use crate::generation::structure::lazily_generate_structure; use crate::generation::structure::placement::should_generate_structure; use crate::generation::structure::structures::{ @@ -54,7 +55,7 @@ use crate::{ block::RawBlockState, chunk::CHUNK_AREA, generation::{biome, positions::chunk_pos}, - world::{BlockAccessor, BlockRegistryExt}, + world::{BlockAccessor, WorldPortalExt}, }; use pumpkin_data::tag::get_tag_ids; use pumpkin_nbt::compound::NbtCompound; @@ -777,6 +778,23 @@ impl ProtoChunk { } } + pub fn spawn_mobs(cache: &mut T, block_registry: &dyn WorldPortalExt) { + let chunk = cache.get_center_chunk(); + debug_assert_eq!(chunk.stage, StagedChunkEnum::Lighting); + + let biome = chunk.get_terrain_gen_biome( + section_to_block(chunk.x), + chunk.bottom_y() as i32 + chunk.height() as i32 - 1, + section_to_block(chunk.z), + ); + let x = chunk.x; + let z = chunk.z; + + block_registry.spawn_mobs_for_chunk_generation(cache, biome, x, z); + + cache.get_center_chunk_mut().stage = StagedChunkEnum::Spawn; + } + #[must_use] pub fn get_terrain_gen_biome_id(&self, x: i32, y: i32, z: i32) -> u8 { // TODO: See if we can cache this value @@ -943,7 +961,7 @@ impl ProtoChunk { /// 2. Then, using the second file, we determine **how** to generate the feature. pub fn generate_features_and_structure( cache: &mut T, - block_registry: &dyn BlockRegistryExt, + block_registry: &dyn WorldPortalExt, random_config: &GlobalRandomConfig, ) { let (center_x, center_z, min_y, height, biomes_in_chunk) = { diff --git a/pumpkin-world/src/level.rs b/pumpkin-world/src/level.rs index 8dc371c4e..ca33bffbd 100644 --- a/pumpkin-world/src/level.rs +++ b/pumpkin-world/src/level.rs @@ -14,8 +14,9 @@ use crate::{ }, generation::get_world_gen, tick::{OrderedTick, ScheduledTick, TickPriority}, - world::BlockRegistryExt, + world::WorldPortalExt, }; +use arc_swap::ArcSwap; use dashmap::{DashMap, Entry}; use pumpkin_config::{chunk::ChunkConfig, lighting::LightingEngineConfig, world::LevelConfig}; use pumpkin_data::biome::Biome; @@ -24,14 +25,11 @@ use pumpkin_data::{Block, block_properties::has_random_ticks, fluid::Fluid}; use pumpkin_util::math::{position::BlockPos, vector2::Vector2}; use pumpkin_util::world_seed::Seed; use rustc_hash::{FxHashMap, FxHashSet}; -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; use std::time::Duration; use std::{ path::PathBuf, - sync::{ - Arc, - atomic::{AtomicBool, AtomicU64, Ordering}, - }, + sync::atomic::{AtomicBool, AtomicU64, Ordering}, thread, }; use tokio::time::timeout; @@ -62,7 +60,7 @@ pub type SyncEntityChunk = Arc; /// For more details on world generation, refer to the `WorldGenerator` module. pub struct Level { pub seed: Seed, - pub block_registry: Arc, + pub world_portal: ArcSwap>>, pub level_folder: LevelFolder, pub lighting_config: LightingEngineConfig, @@ -143,7 +141,6 @@ impl Level { pub fn from_root_folder( level_config: &LevelConfig, root_folder: PathBuf, - block_registry: Arc, seed: i64, dimension: Dimension, gen_pool: Option>, @@ -187,7 +184,7 @@ impl Level { let level_ref = Arc::new(Self { seed, - block_registry, + world_portal: ArcSwap::new(Arc::new(None)), world_gen, level_folder, lighting_config: level_config.lighting, diff --git a/pumpkin-world/src/world.rs b/pumpkin-world/src/world.rs index 59c629a94..915cac2cf 100644 --- a/pumpkin-world/src/world.rs +++ b/pumpkin-world/src/world.rs @@ -1,8 +1,8 @@ use std::pin::Pin; -use crate::BlockStateId; +use crate::{BlockStateId, generation::proto_chunk::GenerationCache}; use bitflags::bitflags; -use pumpkin_data::{Block, BlockState}; +use pumpkin_data::{Block, BlockState, chunk::Biome}; use pumpkin_util::math::position::BlockPos; use thiserror::Error; @@ -55,7 +55,7 @@ impl std::fmt::Display for GetBlockError { pub type WorldFuture<'a, T> = Pin + Send + 'a>>; -pub trait BlockRegistryExt: Send + Sync { +pub trait WorldPortalExt: Send + Sync { fn can_place_at( &self, block: &Block, @@ -63,6 +63,14 @@ pub trait BlockRegistryExt: Send + Sync { block_accessor: &dyn BlockAccessor, block_pos: &BlockPos, ) -> bool; + + fn spawn_mobs_for_chunk_generation( + &self, + cache: &mut dyn GenerationCache, + biome: &'static Biome, + chunk_x: i32, + chunk_z: i32, + ); } pub trait BlockAccessor: Send + Sync { diff --git a/pumpkin/src/block/registry.rs b/pumpkin/src/block/registry.rs index e4c86b7ba..6c0a539f3 100644 --- a/pumpkin/src/block/registry.rs +++ b/pumpkin/src/block/registry.rs @@ -139,7 +139,7 @@ use pumpkin_protocol::java::server::play::SUseItemOn; use pumpkin_util::math::boundingbox::BoundingBox; use pumpkin_util::math::position::BlockPos; use pumpkin_world::BlockStateId; -use pumpkin_world::world::{BlockAccessor, BlockFlags, BlockRegistryExt}; +use pumpkin_world::world::{BlockAccessor, BlockFlags}; use rustc_hash::FxHashMap; use std::sync::Arc; use tokio::sync::Mutex; @@ -372,31 +372,6 @@ pub struct BlockRegistry { fluids: FxHashMap>, } -impl BlockRegistryExt for BlockRegistry { - fn can_place_at( - &self, - block: &pumpkin_data::Block, - state: &BlockState, - block_accessor: &dyn BlockAccessor, - block_pos: &BlockPos, - ) -> bool { - futures::executor::block_on(async move { - self.can_place_at( - None, - None, - block_accessor, - None, - block, - state, - block_pos, - None, - None, - ) - .await - }) - } -} - impl BlockRegistry { pub fn register(&mut self, block: T) { let ids = T::ids(); diff --git a/pumpkin/src/server/mod.rs b/pumpkin/src/server/mod.rs index cad0fb16d..13368534c 100644 --- a/pumpkin/src/server/mod.rs +++ b/pumpkin/src/server/mod.rs @@ -11,6 +11,7 @@ use crate::plugin::PluginManager; use crate::plugin::player::player_login::PlayerLoginEvent; use crate::plugin::server::server_broadcast::ServerBroadcastEvent; use crate::server::tick_rate_manager::ServerTickRateManager; +use crate::world::WorldPortal; use crate::world::custom_bossbar::CustomBossbars; use crate::{ command::node::dispatcher::CommandDispatcher, entity::player::Player, world::World, @@ -25,6 +26,7 @@ use pumpkin_data::entity::EntityType; use pumpkin_util::permission::{PermissionManager, PermissionRegistry}; use pumpkin_util::text::color::NamedColor; use pumpkin_world::dimension::into_level; +use pumpkin_world::world::WorldPortalExt; use tracing::{debug, error, info, warn}; use crate::command::CommandSender; @@ -284,13 +286,14 @@ impl Server { .color_named(NamedColor::DarkGreen) .to_pretty_console() ); - World::load( - into_level(dim, &config, path, registry.clone(), seed, Some(pool)), - l_info, - dim, - registry, - weak, - ) + let level = into_level(dim, &config, path, seed, Some(pool)); + let world = Arc::new(World::load(level.clone(), l_info, dim, registry, weak)); + let portal: Arc = Arc::new(WorldPortal( + world.clone(), + tokio::runtime::Handle::current(), + )); + level.world_portal.store(Arc::new(Some(portal))); + world }) }; @@ -303,9 +306,9 @@ impl Server { ); let worlds_vec = vec![ - Arc::new(overworld.expect("Overworld panicked")), - Arc::new(nether.expect("Nether panicked")), - Arc::new(end.expect("End panicked")), + overworld.expect("Overworld panicked"), + nether.expect("Nether panicked"), + end.expect("End panicked"), ]; server.worlds.store(Arc::new(worlds_vec)); if let Ok(k) = keys { @@ -380,27 +383,21 @@ impl Server { let seed = server.level_info.load().world_gen_settings.seed; // TODO: gen_pool should be reused - let world = World::load( - pumpkin_world::dimension::into_level( - dimension, - &config, - world_path, - registry.clone(), - seed, - None, - ), - l_info, - dimension, - registry, - weak, - ); - let world_arc = Arc::new(world); + let level = + pumpkin_world::dimension::into_level(dimension, &config, world_path, seed, None); + let world: World = World::load(level.clone(), l_info, dimension, registry, weak); + let world = Arc::new(world); + let portal: Arc = Arc::new(WorldPortal( + world.clone(), + tokio::runtime::Handle::current(), + )); + level.world_portal.store(Arc::new(Some(portal))); server.worlds.rcu(|worlds| { let mut new_worlds = (**worlds).clone(); - new_worlds.push(world_arc.clone()); + new_worlds.push(world.clone()); new_worlds }); - world_arc + world }) .await .expect("World creation panicked") diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 001a377a0..9db865310 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -1,7 +1,9 @@ use crate::block::entities::BlockEntity; use dashmap::DashMap; +use pumpkin_data::chunk::Biome; use pumpkin_protocol::bedrock::client::level_event::{CLevelEvent, LevelEvent}; use pumpkin_protocol::codec::data_component::data_to_proto_sound; +use pumpkin_world::generation::proto_chunk::GenerationCache; use std::pin::Pin; use std::sync::atomic::Ordering::Relaxed; use std::sync::{Arc, Weak}; @@ -9,6 +11,7 @@ use std::{ collections::{BTreeMap, HashMap}, sync::atomic::Ordering, }; +use tokio::runtime::Handle; use tracing::{debug, error, info, trace, warn}; pub mod chunker; @@ -121,7 +124,7 @@ use pumpkin_util::{ random::{RandomImpl, get_seed, xoroshiro128::Xoroshiro}, }; use pumpkin_world::inventory::Clearable; -use pumpkin_world::world::GetBlockError; +use pumpkin_world::world::{GetBlockError, WorldPortalExt}; use pumpkin_world::{ BlockStateId, CURRENT_BEDROCK_MC_VERSION, biome, chunk::io::Dirtiable, inventory::Inventory, }; @@ -3187,12 +3190,7 @@ impl World { pub async fn add_entity_silent(&self, entity: Arc) { let base_entity = entity.get_entity(); - // Update biome let block_pos = base_entity.block_pos.load(); - let biome = self.level.get_rough_biome(&block_pos).await; - base_entity.current_biome.store(Arc::new(biome)); - base_entity.last_biome_update_pos.store(block_pos); - let chunk_coordinate = block_pos.chunk_position(); let mut nbt = PNbtCompound::new(); entity.write_nbt(&mut nbt).await; @@ -4303,3 +4301,52 @@ impl BlockAccessor for World { Box::pin(async move { self.get_block_and_state(position).await }) } } + +pub struct WorldPortal(pub Arc, pub Handle); + +// Pure Beauty :cap: +impl WorldPortalExt for WorldPortal { + fn can_place_at( + &self, + block: &pumpkin_data::Block, + state: &BlockState, + block_accessor: &dyn BlockAccessor, + block_pos: &BlockPos, + ) -> bool { + let handle = &self.1; + + handle.block_on(async move { + self.0 + .block_registry + .can_place_at( + None, + None, + block_accessor, + None, + block, + state, + block_pos, + None, + None, + ) + .await + }) + } + + fn spawn_mobs_for_chunk_generation( + &self, + cache: &mut dyn GenerationCache, + biome: &'static Biome, + chunk_x: i32, + chunk_z: i32, + ) { + let handle = &self.1; + + handle.block_on(async move { + natural_spawner::spawn_mobs_for_chunk_generation( + &self.0, cache, biome, chunk_x, chunk_z, + ) + .await; + }); + } +} diff --git a/pumpkin/src/world/natural_spawner.rs b/pumpkin/src/world/natural_spawner.rs index 120352c01..d0462cd34 100644 --- a/pumpkin/src/world/natural_spawner.rs +++ b/pumpkin/src/world/natural_spawner.rs @@ -3,6 +3,7 @@ use crate::entity::r#type::from_type; use crate::world::World; use arc_swap::ArcSwap; use pumpkin_data::biome::Spawner; +use pumpkin_data::chunk::Biome; use pumpkin_data::entity::{EntityType, MobCategory, SpawnLocation}; use pumpkin_data::tag::Block::MINECRAFT_PREVENT_MOB_SPAWNING_INSIDE; use pumpkin_data::tag::Fluid::{MINECRAFT_LAVA, MINECRAFT_WATER}; @@ -20,6 +21,7 @@ use pumpkin_util::random::xoroshiro128::Xoroshiro; use pumpkin_util::random::{RandomImpl, get_seed}; use pumpkin_world::chunk::io::Dirtiable; use pumpkin_world::chunk::{ChunkData, ChunkHeightmapType}; +use pumpkin_world::generation::proto_chunk::GenerationCache; use rand::seq::IndexedRandom; use rand::{RngExt, rng}; use std::fmt; @@ -503,6 +505,126 @@ pub fn get_random_pos_within( BlockPos::new(x, y, z) } +pub async fn spawn_mobs_for_chunk_generation( + world: &Arc, + cache: &mut dyn GenerationCache, + biome: &'static Biome, + chunk_x: i32, + chunk_z: i32, +) { + let mob_settings = &biome.spawners; + let creatures = &mob_settings.creature; + + if creatures.is_empty() { + return; + } + + let xo = chunk_x << 4; + let zo = chunk_z << 4; + + while rand::random::() < biome.creature_spawn_probability { + let Some(spawner_data) = creatures.choose(&mut rand::rng()) else { + continue; + }; + + let count = spawner_data.min_count + + rand::random_range(0..(1 + spawner_data.max_count - spawner_data.min_count).max(1)); + let entity_type = EntityType::from_name( + spawner_data + .r#type + .strip_prefix("minecraft:") + .unwrap_or(spawner_data.r#type), + ) + .unwrap(); + + let mut x = xo + rand::random_range(0..16); + let mut z = zo + rand::random_range(0..16); + let start_x = x; + let start_z = z; + + for _ in 0..count { + let mut success = false; + + // Try 4 times to find a valid spot in the immediate area + for _ in 0..4 { + if success { + break; + } + + let pos = get_top_non_colliding_pos(world, cache, entity_type, x, z); + + if is_spawn_position_ok_cache(cache, &pos, entity_type) { + let spawn_pos_f64 = Vector3::new( + f64::from(pos.0.x) + 0.5, + f64::from(pos.0.y), + f64::from(pos.0.z) + 0.5, + ); + + let entity = from_type(entity_type, spawn_pos_f64, world, Uuid::new_v4()).await; + entity + .get_entity() + .set_rotation(rand::random::() * 360., 0.); + world.spawn_entity(entity).await; + success = true; + } + + // Random jitter for the next mob in the group + x += rand::random_range(0..5) - rand::random_range(0..5); + z += rand::random_range(0..5) - rand::random_range(0..5); + + // Keep group within the chunk bounds + if x < xo || x >= xo + 16 || z < zo || z >= zo + 16 { + x = start_x; + z = start_z; + } + } + } + } +} + +pub fn get_top_non_colliding_pos( + world: &World, + cache: &dyn GenerationCache, + entity_type: &'static EntityType, + x: i32, + z: i32, +) -> BlockPos { + let mut y = cache.get_top_y(&entity_type.spawn_restriction.heightmap, x, z); + let mut pos_vec = Vector3::new(x, y, z); + let min_y = world.min_y; + + if world.dimension.has_ceiling { + loop { + y -= 1; + pos_vec.y = y; + // Use UFCS to avoid the ambiguity error from earlier + if GenerationCache::get_block_state(cache, &pos_vec) + .to_state() + .is_air() + || y <= min_y + { + break; + } + } + + loop { + y -= 1; + pos_vec.y = y; + if !GenerationCache::get_block_state(cache, &pos_vec) + .to_state() + .is_air() + || y <= min_y + { + break; + } + } + } + + let pos = BlockPos::new(x, y, z); + + adjust_spawn_position_cache(cache, pos, entity_type) +} + pub async fn spawn_category_for_position( category: &'static MobCategory, world: &Arc, @@ -768,6 +890,69 @@ pub async fn is_spawn_position_ok( } } +/// Cache-based version of `is_spawn_position_ok` used during world generation. +pub fn is_spawn_position_ok_cache( + cache: &dyn GenerationCache, + block_pos: &BlockPos, + entity_type: &'static EntityType, +) -> bool { + let pos_vec = block_pos.0; + let state = GenerationCache::get_block_state(cache, &pos_vec).to_state(); + + match entity_type.spawn_restriction.location { + SpawnLocation::InLava => { + // During generation, we check the block state's liquid property and tag + state.is_liquid() && Block::from_state_id(state.id).has_tag(&MINECRAFT_LAVA) + } + SpawnLocation::InWater => { + let above_pos = block_pos.up().0; + let above_state = GenerationCache::get_block_state(cache, &above_pos).to_state(); + + state.is_liquid() + && Block::from_state_id(state.id).has_tag(&MINECRAFT_WATER) + && !above_state.is_full_cube() + } + SpawnLocation::OnGround => { + let down_pos = block_pos.down().0; + let up_pos = block_pos.up().0; + + let down = GenerationCache::get_block_state(cache, &down_pos).to_state(); + let up = GenerationCache::get_block_state(cache, &up_pos).to_state(); + + // Logic: solid surface below and low enough light level (if applicable in generation) + let is_valid_spawn_below = + down.is_side_solid(BlockDirection::Up) && down.luminance < 14; + + if is_valid_spawn_below { + is_valid_empty_spawn_block(state) && is_valid_empty_spawn_block(up) + } else { + false + } + } + SpawnLocation::Unrestricted => true, + } +} + +/// Cache-based version of `adjust_spawn_position` used during world generation. +pub fn adjust_spawn_position_cache( + cache: &dyn GenerationCache, + pos: BlockPos, + entity_type: &'static EntityType, +) -> BlockPos { + if matches!( + entity_type.spawn_restriction.location, + SpawnLocation::OnGround + ) { + let below = pos.down(); + let state = GenerationCache::get_block_state(cache, &below.0).to_state(); + + if !state.is_full_cube() && !state.is_liquid() { + return below; + } + } + pos +} + pub async fn adjust_spawn_position( world: &World, pos: BlockPos,