feat(chunk-gen): add mob spawn step
This commit is contained in:
parent
bec18d2443
commit
c23c7c429d
25
Cargo.lock
generated
25
Cargo.lock
generated
@ -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",
|
||||
|
||||
@ -34,6 +34,7 @@ crossbeam.workspace = true
|
||||
|
||||
sha2.workspace = true
|
||||
bitflags.workspace = true
|
||||
arc-swap.workspace = true
|
||||
|
||||
dashmap.workspace = true
|
||||
|
||||
|
||||
@ -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,);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<u8> 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<ChunkStatus> 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<StagedChunkEnum> 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!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
}));
|
||||
|
||||
|
||||
@ -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<dyn BlockRegistryExt>,
|
||||
seed: i64,
|
||||
gen_pool: Option<Arc<rayon::ThreadPool>>,
|
||||
) -> Arc<Level> {
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&self,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
chunk: &T,
|
||||
pos: &BlockPos,
|
||||
) -> bool {
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&self,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
chunk: &T,
|
||||
random: &mut RandomGenerator,
|
||||
pos: BlockPos,
|
||||
|
||||
@ -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<HashMap<String, ConfiguredFeature>> =
|
||||
LazyLock::new(build_configured_features);
|
||||
@ -147,7 +147,7 @@ impl ConfiguredFeature {
|
||||
pub fn generate<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
min_y: i8,
|
||||
height: u16,
|
||||
feature_name: &str, // This placed feature
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
_feature: &str, // This placed feature
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height_limit: u16,
|
||||
_feature: &str,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
_feature: &str, // This placed feature
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
random: &mut RandomGenerator,
|
||||
top: i32,
|
||||
bottom: i32,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
_feature: &str, // This placed feature
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
_feature: &str, // This placed feature
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
_feature_name: &str,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
chunk: &mut T,
|
||||
random: &mut RandomGenerator,
|
||||
pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
_feature: &str,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
_feature: &str, // This placed feature
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
_feature: &str, // This placed feature
|
||||
|
||||
@ -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<PlacedFeatureWrapper>,
|
||||
@ -16,7 +16,7 @@ impl RandomBooleanFeature {
|
||||
pub fn generate<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
min_y: i8,
|
||||
height: u16,
|
||||
feature_name: &str, // This placed feature
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
min_y: i8,
|
||||
height: u16,
|
||||
feature: &str,
|
||||
|
||||
@ -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<RandomFeatureEntry>,
|
||||
@ -21,7 +21,7 @@ impl RandomFeature {
|
||||
pub fn generate<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
min_y: i8,
|
||||
height: u16,
|
||||
feature_name: &str, // This placed feature
|
||||
|
||||
@ -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<crate::generation::feature::placed_features::PlacedFeature>,
|
||||
@ -29,7 +29,7 @@ impl RootSystemFeature {
|
||||
pub fn generate<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
random: &mut RandomGenerator,
|
||||
pos: BlockPos,
|
||||
) {
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
_feature: &str,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
chunk: &mut T,
|
||||
random: &mut RandomGenerator,
|
||||
pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
chunk: &mut T,
|
||||
random: &mut RandomGenerator,
|
||||
pos: BlockPos,
|
||||
|
||||
@ -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<PlacedFeature>,
|
||||
@ -15,7 +15,7 @@ impl SimpleRandomFeature {
|
||||
pub fn generate<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
min_y: i8,
|
||||
height: u16,
|
||||
feature_name: &str, // This placed feature
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
chunk: &mut T,
|
||||
_random: &mut RandomGenerator,
|
||||
pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&self,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
chunk: &mut T,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
placer: &TrunkPlacer,
|
||||
height: u32,
|
||||
start_pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
placer: &TrunkPlacer,
|
||||
height: u32,
|
||||
start_pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
placer: &TrunkPlacer,
|
||||
height: u32,
|
||||
start_pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
placer: &TrunkPlacer,
|
||||
height: u32,
|
||||
start_pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
placer: &TrunkPlacer,
|
||||
height: u32,
|
||||
start_pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
placer: &TrunkPlacer,
|
||||
height: u32,
|
||||
start_pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
placer: &TrunkPlacer,
|
||||
height: u32,
|
||||
start_pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&self,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
placer: &TrunkPlacer,
|
||||
height: u32,
|
||||
start_pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
placer: &TrunkPlacer,
|
||||
height: u32,
|
||||
start_pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
placer: &TrunkPlacer,
|
||||
height: u32,
|
||||
start_pos: BlockPos,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
random: &mut RandomGenerator,
|
||||
min_y: i8,
|
||||
height: u16,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
_block_registry: &dyn BlockRegistryExt,
|
||||
_block_registry: &dyn WorldPortalExt,
|
||||
_min_y: i8,
|
||||
_height: u16,
|
||||
_feature: &str,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &mut T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
min_y: i8,
|
||||
height: u16,
|
||||
feature_name: &str,
|
||||
|
||||
@ -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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &T,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
pos: BlockPos,
|
||||
) -> Box<dyn Iterator<Item = BlockPos>> {
|
||||
let allowed_search_condition = self
|
||||
@ -339,7 +339,7 @@ pub struct BlockFilterPlacementModifier {
|
||||
impl ConditionalPlacementModifier for BlockFilterPlacementModifier {
|
||||
fn should_place<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&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<T: GenerationCache>(
|
||||
&self,
|
||||
block_registry: &dyn BlockRegistryExt,
|
||||
block_registry: &dyn WorldPortalExt,
|
||||
feature: &str,
|
||||
chunk: &T,
|
||||
random: &mut RandomGenerator,
|
||||
|
||||
@ -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<T: GenerationCache>(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<T: GenerationCache>(
|
||||
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) = {
|
||||
|
||||
@ -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<ChunkEntityData>;
|
||||
/// For more details on world generation, refer to the `WorldGenerator` module.
|
||||
pub struct Level {
|
||||
pub seed: Seed,
|
||||
pub block_registry: Arc<dyn BlockRegistryExt>,
|
||||
pub world_portal: ArcSwap<Option<Arc<dyn WorldPortalExt>>>,
|
||||
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<dyn BlockRegistryExt>,
|
||||
seed: i64,
|
||||
dimension: Dimension,
|
||||
gen_pool: Option<Arc<rayon::ThreadPool>>,
|
||||
@ -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,
|
||||
|
||||
@ -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<Box<dyn Future<Output = T> + 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 {
|
||||
|
||||
@ -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<u16, Arc<dyn FluidBehaviour>>,
|
||||
}
|
||||
|
||||
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<T: BlockBehaviour + BlockMetadata + 'static>(&mut self, block: T) {
|
||||
let ids = T::ids();
|
||||
|
||||
@ -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<dyn WorldPortalExt> = 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<dyn WorldPortalExt> = 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")
|
||||
|
||||
@ -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<dyn EntityBase>) {
|
||||
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<World>, 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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<World>,
|
||||
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::<f32>() < 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::<f32>() * 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<World>,
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user