feat: guess living entities
This commit is contained in:
parent
57db90ce1a
commit
0555f804e0
@ -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);
|
||||
|
||||
@ -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<String, i32> =
|
||||
let handlers_map: BTreeMap<String, i32> =
|
||||
serde_json::from_str(&fs::read_to_string("../assets/meta_data_type.json").unwrap())
|
||||
.expect("Failed to parse meta_data_type.json");
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
})
|
||||
|
||||
@ -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,
|
||||
})
|
||||
|
||||
@ -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>(
|
||||
|
||||
@ -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())
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -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>,
|
||||
}
|
||||
|
||||
@ -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,
|
||||
})
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -559,40 +559,41 @@ impl World {
|
||||
pub async fn tick(self: &Arc<Self>, 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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>, f64); // pos charge
|
||||
struct PointCharge(Vector3<f64>, 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<i32>,
|
||||
chunk: &Arc<RwLock<ChunkData>>,
|
||||
) -> 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::<f32>() * 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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user