From 0555f804e0c7148ac49af0546de0ccb1fea51c7f Mon Sep 17 00:00:00 2001 From: Alexander Medvedev Date: Tue, 13 Jan 2026 23:36:49 +0100 Subject: [PATCH] feat: guess living entities --- pumpkin-data/build/block.rs | 27 ++++++++---- pumpkin-data/build/meta_data_type.rs | 4 +- pumpkin-world/src/chunk/mod.rs | 13 +++--- .../src/generation/block_predicate.rs | 4 +- .../src/generation/feature/features/bamboo.rs | 5 ++- .../features/nether_forest_vegetation.rs | 4 +- .../feature/features/simple_block.rs | 4 +- pumpkin-world/src/world.rs | 2 +- pumpkin/src/block/blocks/fire/fire.rs | 4 +- pumpkin/src/block/blocks/fire/mod.rs | 4 +- pumpkin/src/block/blocks/grindstone.rs | 7 +--- pumpkin/src/block/blocks/ladder.rs | 7 ++-- pumpkin/src/block/blocks/redstone/buttons.rs | 9 +++- pumpkin/src/block/blocks/redstone/lever.rs | 9 +++- .../block/blocks/redstone/tripwire_hook.rs | 11 ++++- pumpkin/src/block/mod.rs | 2 +- pumpkin/src/block/registry.rs | 8 ++-- pumpkin/src/entity/type.rs | 13 ++++-- pumpkin/src/net/java/play.rs | 2 +- pumpkin/src/world/mod.rs | 39 +++++++++++------- pumpkin/src/world/natural_spawner.rs | 41 +++++++++++-------- 21 files changed, 135 insertions(+), 84 deletions(-) diff --git a/pumpkin-data/build/block.rs b/pumpkin-data/build/block.rs index bbbffd45a..d0cff878f 100644 --- a/pumpkin-data/build/block.rs +++ b/pumpkin-data/build/block.rs @@ -279,8 +279,9 @@ impl ToTokens for BlockPropertyStruct { } #[inline] + #[allow(clippy::manual_range_patterns)] fn handles_block_id(block_id: u16) -> bool where Self: Sized { - [#(#block_ids),*].contains(&block_id) + matches!(block_id, #(#block_ids)|*) } fn to_state_id(&self, block: &Block) -> u16 { @@ -291,14 +292,22 @@ impl ToTokens for BlockPropertyStruct { } fn from_state_id(state_id: u16, block: &Block) -> Self { - if !Self::handles_block_id(block.id) { - panic!("{} is not a valid block for {}", &block.name, #struct_name); - } - if state_id >= block.states[0].id && state_id <= block.states.last().unwrap().id { - let index = state_id - block.states[0].id; - Self::from_index(index) + debug_assert!( + Self::handles_block_id(block.id), + "{} is not a valid block for {}", &block.name, #struct_name + ); + + let min_id = block.states[0].id; + let max_id = block.states.last().map(|s| s.id).unwrap_or(min_id); + + if (min_id..=max_id).contains(&state_id) { + Self::from_index(state_id - min_id) } else { + #[cfg(debug_assertions)] panic!("State ID {} does not exist for {}", state_id, &block.name); + + #[cfg(not(debug_assertions))] + Self::from_index(0) } } @@ -313,8 +322,10 @@ impl ToTokens for BlockPropertyStruct { vec![ #(#to_props_entries),* ] } + #[allow(clippy::manual_range_patterns)] fn from_props(props: &[(&str, &str)], block: &Block) -> Self { - if ![#(#block_ids),*].contains(&block.id) { + #[cfg(debug_assertions)] + if !matches!(block.id, #(#block_ids)|*) { panic!("{} is not a valid block for {}", &block.name, #struct_name); } let mut block_props = Self::default(block); diff --git a/pumpkin-data/build/meta_data_type.rs b/pumpkin-data/build/meta_data_type.rs index be64a0c79..124ba055e 100644 --- a/pumpkin-data/build/meta_data_type.rs +++ b/pumpkin-data/build/meta_data_type.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fs}; +use std::{collections::BTreeMap, fs}; use heck::ToPascalCase; use proc_macro2::TokenStream; @@ -7,7 +7,7 @@ use quote::{format_ident, quote}; pub(crate) fn build() -> TokenStream { println!("cargo:rerun-if-changed=../assets/meta_data_type.json"); - let handlers_map: HashMap = + let handlers_map: BTreeMap = serde_json::from_str(&fs::read_to_string("../assets/meta_data_type.json").unwrap()) .expect("Failed to parse meta_data_type.json"); diff --git a/pumpkin-world/src/chunk/mod.rs b/pumpkin-world/src/chunk/mod.rs index 3b2ff2a9d..effabf0e1 100644 --- a/pumpkin-world/src/chunk/mod.rs +++ b/pumpkin-world/src/chunk/mod.rs @@ -218,13 +218,7 @@ impl ChunkHeightmaps { data[packed_array_idx] = data[packed_array_idx].bitand(mask).bitor(height); } - pub fn get_height(&self, _type: ChunkHeightmapType, x: i32, z: i32, min_y: i32) -> i32 { - let data = match _type { - ChunkHeightmapType::WorldSurface => &self.world_surface, - ChunkHeightmapType::MotionBlocking => &self.motion_blocking, - ChunkHeightmapType::MotionBlockingNoLeaves => &self.motion_blocking_no_leaves, - }; - + pub fn get_height(&self, heightmap: ChunkHeightmapType, x: i32, z: i32, min_y: i32) -> i32 { let local_x = (x & 15) as usize; let local_z = (z & 15) as usize; @@ -244,6 +238,11 @@ impl ChunkHeightmaps { let packed_array_idx = column_idx / 7; + let data = match heightmap { + ChunkHeightmapType::WorldSurface => &self.world_surface, + ChunkHeightmapType::MotionBlocking => &self.motion_blocking, + ChunkHeightmapType::MotionBlockingNoLeaves => &self.motion_blocking_no_leaves, + }; let height_bit_bytes_i64 = data[packed_array_idx].bitand(mask).to_ne_bytes(); (u64::from_ne_bytes(height_bit_bytes_i64) diff --git a/pumpkin-world/src/generation/block_predicate.rs b/pumpkin-world/src/generation/block_predicate.rs index ac22c9ab8..777972109 100644 --- a/pumpkin-world/src/generation/block_predicate.rs +++ b/pumpkin-world/src/generation/block_predicate.rs @@ -239,8 +239,10 @@ impl WouldSurviveBlockPredicate { pos: &BlockPos, ) -> bool { let block = self.state.get_block(); + let state = self.state.get_state(); + let pos = self.offset.get(pos); - block_registry.can_place_at(block, chunk, &pos, BlockDirection::Up) + block_registry.can_place_at(block, state, chunk, &pos) } } diff --git a/pumpkin-world/src/generation/feature/features/bamboo.rs b/pumpkin-world/src/generation/feature/features/bamboo.rs index ea722c8f2..d118e82c2 100644 --- a/pumpkin-world/src/generation/feature/features/bamboo.rs +++ b/pumpkin-world/src/generation/feature/features/bamboo.rs @@ -1,5 +1,5 @@ use pumpkin_data::{ - Block, BlockDirection, BlockState, + Block, BlockState, block_properties::{BambooLeaves, BambooLikeProperties, BlockProperties, Integer0To1}, tag, tag::Taggable, @@ -32,7 +32,8 @@ impl BambooFeature { ) -> bool { let mut i = 0; if chunk.is_air(&pos.0) { - if block_registry.can_place_at(&Block::BAMBOO, chunk, &pos, BlockDirection::Up) { + if block_registry.can_place_at(&Block::BAMBOO, Block::BAMBOO.default_state, chunk, &pos) + { let height = random.next_bounded_i32(12) + 5; if random.next_f32() < self.probability { let rnd = random.next_bounded_i32(4) + 1; 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 3b2a1e439..b633dd3a6 100644 --- a/pumpkin-world/src/generation/feature/features/nether_forest_vegetation.rs +++ b/pumpkin-world/src/generation/feature/features/nether_forest_vegetation.rs @@ -1,4 +1,4 @@ -use pumpkin_data::{Block, BlockDirection, tag, tag::Taggable}; +use pumpkin_data::{Block, tag, tag::Taggable}; use pumpkin_util::{ math::position::BlockPos, random::{RandomGenerator, RandomImpl}, @@ -47,7 +47,7 @@ impl NetherForestVegetationFeature { let nether_block = Block::from_state_id(nether_state.id); if !chunk.is_air(&pos.0) || pos.0.y <= chunk.bottom_y() as i32 - || block_registry.can_place_at(nether_block, chunk, &pos, BlockDirection::Up) + || block_registry.can_place_at(nether_block, nether_state, chunk, &pos) { continue; } diff --git a/pumpkin-world/src/generation/feature/features/simple_block.rs b/pumpkin-world/src/generation/feature/features/simple_block.rs index a8a33ea27..4ab034329 100644 --- a/pumpkin-world/src/generation/feature/features/simple_block.rs +++ b/pumpkin-world/src/generation/feature/features/simple_block.rs @@ -1,4 +1,4 @@ -use pumpkin_data::{Block, BlockDirection}; +use pumpkin_data::Block; use pumpkin_util::{math::position::BlockPos, random::RandomGenerator}; use serde::Deserialize; @@ -25,7 +25,7 @@ impl SimpleBlockFeature { let state = self.to_place.get(random, pos); let block = Block::from_state_id(state.id); let block_accessor: &dyn BlockAccessor = chunk; - if !block_registry.can_place_at(block, block_accessor, &pos, BlockDirection::Up) { + if !block_registry.can_place_at(block, state, block_accessor, &pos) { return false; } diff --git a/pumpkin-world/src/world.rs b/pumpkin-world/src/world.rs index e36b6cf8d..46b405337 100644 --- a/pumpkin-world/src/world.rs +++ b/pumpkin-world/src/world.rs @@ -121,9 +121,9 @@ pub trait BlockRegistryExt: Send + Sync { fn can_place_at( &self, block: &Block, + state: &BlockState, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos, - face: BlockDirection, ) -> bool; } diff --git a/pumpkin/src/block/blocks/fire/fire.rs b/pumpkin/src/block/blocks/fire/fire.rs index 13e7c32d4..a773992a1 100644 --- a/pumpkin/src/block/blocks/fire/fire.rs +++ b/pumpkin/src/block/blocks/fire/fire.rs @@ -224,8 +224,8 @@ impl BlockBehaviour for FireBlock { world: Some(args.world), block_accessor: args.world, block: &Block::FIRE, + state: Block::FIRE.default_state, position: args.position, - direction: BlockDirection::Up, player: None, use_item_on: None, }) @@ -275,8 +275,8 @@ impl BlockBehaviour for FireBlock { world: Some(world), block_accessor: world.as_ref(), block, + state: block.default_state, position: pos, - direction: BlockDirection::Up, player: None, use_item_on: None, }) diff --git a/pumpkin/src/block/blocks/fire/mod.rs b/pumpkin/src/block/blocks/fire/mod.rs index 6e19f72b3..56051d1e7 100644 --- a/pumpkin/src/block/blocks/fire/mod.rs +++ b/pumpkin/src/block/blocks/fire/mod.rs @@ -56,8 +56,8 @@ impl FireBlockBase { world: Some(world), block_accessor: world.as_ref(), block: &Block::SOUL_FIRE, + state: Block::SOUL_FIRE.default_state, position: block_pos, - direction: BlockDirection::Up, player: None, use_item_on: None, }) @@ -69,8 +69,8 @@ impl FireBlockBase { world: Some(world), block_accessor: world.as_ref(), block: &Block::FIRE, + state: Block::FIRE.default_state, position: block_pos, - direction: BlockDirection::Up, player: None, use_item_on: None, }) diff --git a/pumpkin/src/block/blocks/grindstone.rs b/pumpkin/src/block/blocks/grindstone.rs index 5a898e02c..86bb21fc8 100644 --- a/pumpkin/src/block/blocks/grindstone.rs +++ b/pumpkin/src/block/blocks/grindstone.rs @@ -27,11 +27,8 @@ impl BlockBehaviour for GrindstoneBlock { }) } - fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> { - Box::pin(async move { - WallMountedBlock::can_place_at(self, args.block_accessor, args.position, args.direction) - .await - }) + fn can_place_at<'a>(&'a self, _args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> { + Box::pin(async move { true }) } fn get_state_for_neighbor_update<'a>( diff --git a/pumpkin/src/block/blocks/ladder.rs b/pumpkin/src/block/blocks/ladder.rs index ea98e79ea..05c43e99c 100644 --- a/pumpkin/src/block/blocks/ladder.rs +++ b/pumpkin/src/block/blocks/ladder.rs @@ -3,9 +3,9 @@ use crate::block::{ OnScheduledTickArgs, }; use crate::world::World; -use pumpkin_data::BlockDirection; use pumpkin_data::block_properties::HorizontalFacing; use pumpkin_data::block_properties::{BlockProperties, LadderLikeProperties}; +use pumpkin_data::{BlockDirection, HorizontalFacingExt}; use pumpkin_macros::pumpkin_block; use pumpkin_util::math::position::BlockPos; use pumpkin_world::BlockStateId; @@ -25,11 +25,12 @@ impl BlockBehaviour for LadderBlock { } fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> { Box::pin(async move { + let props = LadderLikeProperties::from_state_id(args.state.id, args.block); + args.block_accessor .get_block_state(&args.use_item_on.unwrap().position) .await - .is_side_solid(args.direction.opposite()) - && args.direction.is_horizontal() + .is_side_solid(props.facing.opposite().to_block_direction()) }) } diff --git a/pumpkin/src/block/blocks/redstone/buttons.rs b/pumpkin/src/block/blocks/redstone/buttons.rs index 84909c39c..b4706c5f1 100644 --- a/pumpkin/src/block/blocks/redstone/buttons.rs +++ b/pumpkin/src/block/blocks/redstone/buttons.rs @@ -138,8 +138,13 @@ impl BlockBehaviour for ButtonBlock { fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> { Box::pin(async move { - WallMountedBlock::can_place_at(self, args.block_accessor, args.position, args.direction) - .await + WallMountedBlock::can_place_at( + self, + args.block_accessor, + args.position, + self.get_direction(args.state.id, args.block), + ) + .await }) } diff --git a/pumpkin/src/block/blocks/redstone/lever.rs b/pumpkin/src/block/blocks/redstone/lever.rs index b5e7731a2..87e0d5792 100644 --- a/pumpkin/src/block/blocks/redstone/lever.rs +++ b/pumpkin/src/block/blocks/redstone/lever.rs @@ -104,8 +104,13 @@ impl BlockBehaviour for LeverBlock { fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> { Box::pin(async move { - WallMountedBlock::can_place_at(self, args.block_accessor, args.position, args.direction) - .await + WallMountedBlock::can_place_at( + self, + args.block_accessor, + args.position, + self.get_direction(args.state.id, args.block), + ) + .await }) } diff --git a/pumpkin/src/block/blocks/redstone/tripwire_hook.rs b/pumpkin/src/block/blocks/redstone/tripwire_hook.rs index 746143529..ef978e45e 100644 --- a/pumpkin/src/block/blocks/redstone/tripwire_hook.rs +++ b/pumpkin/src/block/blocks/redstone/tripwire_hook.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use pumpkin_data::{ - Block, BlockDirection, + Block, BlockDirection, HorizontalFacingExt, block_properties::BlockProperties, sound::{Sound, SoundCategory}, }; @@ -45,7 +45,14 @@ impl BlockBehaviour for TripwireHookBlock { fn can_place_at<'a>(&'a self, args: CanPlaceAtArgs<'a>) -> BlockFuture<'a, bool> { Box::pin(async move { - Self::can_place_at(args.block_accessor, args.position, args.direction).await + let props = TripwireHookProperties::from_state_id(args.state.id, args.block); + + Self::can_place_at( + args.block_accessor, + args.position, + props.facing.to_block_direction(), + ) + .await }) } diff --git a/pumpkin/src/block/mod.rs b/pumpkin/src/block/mod.rs index 0a1ff175c..b2a370a90 100644 --- a/pumpkin/src/block/mod.rs +++ b/pumpkin/src/block/mod.rs @@ -230,8 +230,8 @@ pub struct CanPlaceAtArgs<'a> { pub world: Option<&'a World>, pub block_accessor: &'a dyn BlockAccessor, pub block: &'a Block, + pub state: &'a BlockState, pub position: &'a BlockPos, - pub direction: BlockDirection, pub player: Option<&'a Player>, pub use_item_on: Option<&'a SUseItemOn>, } diff --git a/pumpkin/src/block/registry.rs b/pumpkin/src/block/registry.rs index c3d4a7acb..ab6355029 100644 --- a/pumpkin/src/block/registry.rs +++ b/pumpkin/src/block/registry.rs @@ -306,9 +306,9 @@ impl BlockRegistryExt for BlockRegistry { fn can_place_at( &self, block: &pumpkin_data::Block, + state: &BlockState, block_accessor: &dyn BlockAccessor, block_pos: &BlockPos, - face: BlockDirection, ) -> bool { futures::executor::block_on(async move { self.can_place_at( @@ -317,8 +317,8 @@ impl BlockRegistryExt for BlockRegistry { block_accessor, None, block, + state, block_pos, - face, None, ) .await @@ -493,8 +493,8 @@ impl BlockRegistry { block_accessor: &dyn BlockAccessor, player: Option<&Player>, block: &Block, + state: &BlockState, position: &BlockPos, - direction: BlockDirection, use_item_on: Option<&SUseItemOn>, ) -> bool { let pumpkin_block = self.get_pumpkin_block(block); @@ -505,8 +505,8 @@ impl BlockRegistry { world, block_accessor, block, + state, position, - direction, player, use_item_on, }) diff --git a/pumpkin/src/entity/type.rs b/pumpkin/src/entity/type.rs index 0ef61d313..c8c73dd0a 100644 --- a/pumpkin/src/entity/type.rs +++ b/pumpkin/src/entity/type.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use pumpkin_data::entity::EntityType; +use pumpkin_data::entity::{EntityType, MobCategory}; use pumpkin_util::math::vector3::Vector3; use uuid::Uuid; @@ -8,6 +8,7 @@ use crate::{ entity::{ Entity, EntityBase, decoration::{end_crystal::EndCrystalEntity, painting::PaintingEntity}, + living::LivingEntity, mob::zombie::Zombie, }, world::World, @@ -25,8 +26,14 @@ pub async fn from_type( id if id == EntityType::ZOMBIE.id => Zombie::make(entity).await, id if id == EntityType::PAINTING.id => Arc::new(PaintingEntity::new(entity)), id if id == EntityType::END_CRYSTAL.id => Arc::new(EndCrystalEntity::new(entity)), - // TODO - _ => Arc::new(entity), // Fallback Entity + // Fallback Entity + _ => { + if entity_type.category == &MobCategory::MISC { + Arc::new(entity) + } else { + Arc::new(LivingEntity::new(entity)) + } + } }; mob diff --git a/pumpkin/src/net/java/play.rs b/pumpkin/src/net/java/play.rs index 6fdac78ec..2773eb57f 100644 --- a/pumpkin/src/net/java/play.rs +++ b/pumpkin/src/net/java/play.rs @@ -1999,8 +1999,8 @@ impl JavaClient { world.as_ref(), Some(player), block, + block.default_state, &final_block_pos, - final_face, Some(&use_item_on), ) .await diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 725c9ad2b..1a6053bda 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -559,40 +559,41 @@ impl World { pub async fn tick(self: &Arc, server: &Server) { let start = tokio::time::Instant::now(); + // 1. Block & Environment self.flush_block_updates().await; - // tick block entities self.flush_synced_block_events().await; - self.tick_environment().await; + let env_done = start.elapsed(); + // 2. Chunks let chunk_start = tokio::time::Instant::now(); - // log::debug!("Ticking chunks"); self.tick_chunks().await; let chunk_elapsed = chunk_start.elapsed(); + // 3. Players + let player_start = tokio::time::Instant::now(); let players_to_tick: Vec<_> = self.players.read().await.values().cloned().collect(); - - // log::debug!("Ticking players"); - // player ticks - for player in players_to_tick { + let player_count = players_to_tick.len(); + for player in &players_to_tick { player.tick(server).await; } + let player_elapsed = player_start.elapsed(); + // 4. Entities & Collision + let entity_start = tokio::time::Instant::now(); let entities_to_tick: Vec<_> = self.entities.read().await.values().cloned().collect(); + let entity_count = entities_to_tick.len(); - // log::debug!("Ticking entities"); - // Entity ticks for entity in entities_to_tick { entity.get_entity().age.fetch_add(1, Relaxed); - entity.tick(entity.clone(), server).await; - for player in self.players.read().await.values() { + + for player in &players_to_tick { if player .living_entity .entity .bounding_box .load() - // This is vanilla, but TODO: change this when is in a vehicle .expand(1.0, 0.5, 1.0) .intersects(&entity.get_entity().bounding_box.load()) { @@ -601,14 +602,22 @@ impl World { } } } + let entity_elapsed = entity_start.elapsed(); self.level.chunk_loading.lock().unwrap().send_change(); - if start.elapsed().as_millis() > 50 { + // 5. Detailed Slow Tick Logging + let total_elapsed = start.elapsed(); + if total_elapsed.as_millis() > 50 { log::warn!( - "Slow Tick: Total {:?} | Chunks {:?}", - start.elapsed(), + "Slow Tick [{}ms]: Chunks: {:?} | Players({}): {:?} | Entities({}): {:?} | Env: {:?}", + total_elapsed.as_millis(), chunk_elapsed, + player_count, + player_elapsed, + entity_count, + entity_elapsed, + env_done ); } } diff --git a/pumpkin/src/world/natural_spawner.rs b/pumpkin/src/world/natural_spawner.rs index 6bfdd60c5..277762b6b 100644 --- a/pumpkin/src/world/natural_spawner.rs +++ b/pumpkin/src/world/natural_spawner.rs @@ -14,6 +14,8 @@ use pumpkin_util::math::get_section_cord; use pumpkin_util::math::position::BlockPos; use pumpkin_util::math::vector2::Vector2; use pumpkin_util::math::vector3::Vector3; +use pumpkin_util::random::xoroshiro128::Xoroshiro; +use pumpkin_util::random::{RandomImpl, get_seed}; use pumpkin_world::chunk::{ChunkData, ChunkHeightmapType}; use rand::seq::IndexedRandom; use rand::{Rng, rng}; @@ -131,7 +133,7 @@ impl LocalMobCapCalculator { } #[derive(Debug)] -struct PointCharge(Vector3, f64); // pos charge +struct PointCharge(Vector3, f64); impl PointCharge { fn get_potential_change(&self, pos: &BlockPos) -> f64 { @@ -296,13 +298,23 @@ pub fn get_filtered_spawning_categories( spawn_enemies: bool, spawn_passives: bool, ) -> Vec<&'static MobCategory> { - let mut ret = Vec::with_capacity(8); + let mut ret = Vec::with_capacity(MobCategory::SPAWNING_CATEGORIES.len()); for category in MobCategory::SPAWNING_CATEGORIES { - if (spawn_friendlies || !category.is_friendly) - && (spawn_enemies || category.is_friendly) - && (spawn_passives || !category.is_persistent) - && state.can_spawn_for_category_global(category) - { + let is_type_allowed = if category.is_friendly { + spawn_friendlies + } else { + spawn_enemies + }; + + if !is_type_allowed { + continue; + } + + if category.is_persistent && !spawn_passives { + continue; + } + + if state.can_spawn_for_category_global(category) { ret.push(category); } } @@ -323,7 +335,6 @@ pub async fn spawn_for_chunk( .await { let random_pos = get_random_pos_within(world.min_y, chunk_pos, chunk).await; - // debug!("try random pos: {:?}", random_pos); if random_pos.0.y > world.min_y { spawn_category_for_position(category, world, random_pos, chunk_pos, spawn_state) .await; @@ -336,8 +347,10 @@ pub async fn get_random_pos_within( chunk_pos: &Vector2, chunk: &Arc>, ) -> BlockPos { - let x = (chunk_pos.x << 4) + rng().random_range(0..16); - let z = (chunk_pos.y << 4) + rng().random_range(0..16); + let mut rng = Xoroshiro::from_seed(get_seed()); + + let x = (chunk_pos.x << 4) + rng.next_bounded_i32(16); + let z = (chunk_pos.y << 4) + rng.next_bounded_i32(16); let temp_y = chunk .read() @@ -345,7 +358,7 @@ pub async fn get_random_pos_within( .heightmap .get_height(ChunkHeightmapType::WorldSurface, x, z, min_y) + 1; - let y = rng().random_range(min_y..=temp_y); + let y = rng.next_inbetween_i32(min_y, temp_y); BlockPos::new(x, y, z) } @@ -365,8 +378,6 @@ pub async fn spawn_category_for_position( let mut new_z = new_pos.0.z; let mut random_group_size = (rng().random::() * 4.).ceil() as i32; let mut inc = 0; - #[expect(unused_variables)] - let group_size = 0; 'outer: while inc < random_group_size { new_x += rng().random_range(0..6) - rng().random_range(0..6); new_z += rng().random_range(0..6) - rng().random_range(0..6); @@ -379,12 +390,10 @@ pub async fn spawn_category_for_position( world, chunk_pos, ) { - // debug!("{new_pos:?} failed, too near to player or spawn point dst: {player_distance}"); inc += 1; continue; } let Some(spawner) = get_random_spawn_mob_at(world, category, &new_pos).await else { - // debug!("{new_pos:?} failed, no random spawn mob at category: {category:?}"); break 'outer; }; random_group_size = rng().random_range(spawner.min_count..=spawner.max_count); @@ -399,12 +408,10 @@ pub async fn spawn_category_for_position( ) .await { - // debug!("{new_pos:?} failed, not valid spawn position"); inc += 1; continue; } if !spawn_state.can_spawn(entity_type, &new_pos, world).await { - // debug!("{new_pos:?} failed, can't spawn at"); inc += 1; continue; }