fix: wrong entity spawner values
This commit is contained in:
parent
5627b182d6
commit
a75ea9ed11
@ -150,7 +150,6 @@ interface event {
|
||||
player: player,
|
||||
action: interact-action,
|
||||
clicked-pos: option<block-position>,
|
||||
item: item-stack,
|
||||
block: string,
|
||||
cancelled: bool
|
||||
}
|
||||
|
||||
@ -337,18 +337,6 @@ impl Level {
|
||||
self.chunk_saver.block_and_await_ongoing_tasks().await;
|
||||
self.entity_saver.block_and_await_ongoing_tasks().await;
|
||||
|
||||
// save all chunks currently in memory
|
||||
// let chunks_to_write = self
|
||||
// .loaded_chunks
|
||||
// .iter()
|
||||
// .map(|chunk| (*chunk.key(), chunk.value().clone()))
|
||||
// .collect::<Vec<_>>();
|
||||
// self.loaded_chunks.clear();
|
||||
|
||||
// TODO: I think the chunk_saver should be at the server level
|
||||
// self.chunk_saver.clear_watched_chunks().await;
|
||||
// self.write_chunks(chunks_to_write).await;
|
||||
|
||||
// save all chunks currently in memory
|
||||
let chunks_to_write = self
|
||||
.loaded_entity_chunks
|
||||
@ -383,9 +371,6 @@ impl Level {
|
||||
.or_insert(1);
|
||||
}
|
||||
|
||||
// self.chunk_saver
|
||||
// .watch_chunks(&self.level_folder, chunks)
|
||||
// .await;
|
||||
self.entity_saver
|
||||
.watch_chunks(&self.level_folder, chunks)
|
||||
.await;
|
||||
@ -539,23 +524,25 @@ impl Level {
|
||||
self.chunk_watchers.shrink_to_fit();
|
||||
}
|
||||
|
||||
// if the difference is too big, we can shrink the loaded chunks
|
||||
// (1024 chunks is the equivalent to a 32x32 chunks area)
|
||||
// if self.loaded_chunks.capacity() - self.loaded_chunks.len() >= 4096 {
|
||||
// self.loaded_chunks.shrink_to_fit();
|
||||
// }
|
||||
|
||||
if self.loaded_entity_chunks.capacity() - self.loaded_entity_chunks.len() >= 4096 {
|
||||
self.loaded_entity_chunks.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_chunk(self: &Arc<Self>, pos: Vector2<i32>) -> SyncChunk {
|
||||
pub async fn get_or_fetch_chunk<R, F: Fn(&SyncChunk) -> R>(
|
||||
self: &Arc<Self>,
|
||||
pos: Vector2<i32>,
|
||||
f: F,
|
||||
) -> R {
|
||||
// Check if already in memory
|
||||
if let Some(chunk) = self.loaded_chunks.get(&pos) {
|
||||
return chunk.clone();
|
||||
if let Some(res) = self.read_chunk_sync(&pos, &f) {
|
||||
return res;
|
||||
}
|
||||
let chunk = self.fetch_chunk(pos).await;
|
||||
f(&chunk)
|
||||
}
|
||||
|
||||
async fn fetch_chunk(self: &Arc<Self>, pos: Vector2<i32>) -> SyncChunk {
|
||||
let recv = self.chunk_listener.add_single_chunk_listener(pos);
|
||||
|
||||
{
|
||||
@ -564,12 +551,9 @@ impl Level {
|
||||
lock.send_change();
|
||||
};
|
||||
|
||||
let chunk = if let Some(chunk) = self.loaded_chunks.get(&pos) {
|
||||
chunk.clone()
|
||||
} else {
|
||||
recv.await
|
||||
.expect("Chunk listener dropped without sending chunk")
|
||||
};
|
||||
let chunk = recv
|
||||
.await
|
||||
.expect("Chunk listener dropped without sending chunk");
|
||||
|
||||
{
|
||||
let mut lock = self.chunk_loading.lock().unwrap();
|
||||
@ -694,31 +678,30 @@ impl Level {
|
||||
|
||||
pub async fn get_block_state(self: &Arc<Self>, position: &BlockPos) -> RawBlockState {
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
let chunk = self.get_chunk(chunk_coordinate).await;
|
||||
|
||||
let Some(id) = chunk.section.get_block_absolute_y(
|
||||
let id = self
|
||||
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
|
||||
chunk.section.get_block_absolute_y(
|
||||
relative.x as usize,
|
||||
relative.y,
|
||||
relative.z as usize,
|
||||
) else {
|
||||
return RawBlockState(Block::VOID_AIR.default_state.id);
|
||||
};
|
||||
|
||||
RawBlockState(id)
|
||||
)
|
||||
})
|
||||
.await;
|
||||
RawBlockState(id.unwrap_or(Block::VOID_AIR.default_state.id))
|
||||
}
|
||||
|
||||
pub async fn get_rough_biome(self: &Arc<Self>, position: &BlockPos) -> &'static Biome {
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
let chunk = self.get_chunk(chunk_coordinate).await;
|
||||
|
||||
let Some(id) = chunk.section.get_rough_biome_absolute_y(
|
||||
let id = self
|
||||
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
|
||||
chunk.section.get_rough_biome_absolute_y(
|
||||
relative.x as usize,
|
||||
relative.y,
|
||||
relative.z as usize,
|
||||
) else {
|
||||
return &Biome::THE_VOID;
|
||||
};
|
||||
|
||||
Biome::from_id(id).unwrap()
|
||||
)
|
||||
})
|
||||
.await;
|
||||
Biome::from_id(id.unwrap_or(0)).unwrap_or(&Biome::THE_VOID)
|
||||
}
|
||||
|
||||
pub async fn set_block_state(
|
||||
@ -727,7 +710,7 @@ impl Level {
|
||||
block_state_id: BlockStateId,
|
||||
) -> BlockStateId {
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
let chunk = self.get_chunk(chunk_coordinate).await;
|
||||
self.get_or_fetch_chunk(chunk_coordinate, |chunk| {
|
||||
let replaced_block_state_id = chunk.section.set_block_absolute_y(
|
||||
relative.x as usize,
|
||||
relative.y,
|
||||
@ -738,6 +721,8 @@ impl Level {
|
||||
chunk.mark_dirty(true);
|
||||
}
|
||||
replaced_block_state_id
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn write_chunks(&self, chunks_to_write: Vec<(Vector2<i32>, SyncChunk)>) {
|
||||
@ -780,6 +765,40 @@ impl Level {
|
||||
.map(|x| x.value().clone())
|
||||
}
|
||||
|
||||
pub fn is_chunk_loaded(&self, coordinates: &Vector2<i32>) -> bool {
|
||||
self.loaded_chunks.contains_key(coordinates)
|
||||
}
|
||||
|
||||
pub fn read_chunk_sync<R, F: Fn(&SyncChunk) -> R>(
|
||||
&self,
|
||||
coordinates: &Vector2<i32>,
|
||||
f: F,
|
||||
) -> Option<R> {
|
||||
self.loaded_chunks.get(coordinates).map(|x| f(x.value()))
|
||||
}
|
||||
|
||||
pub fn read_entity_chunk_sync<R, F: Fn(&SyncEntityChunk) -> R>(
|
||||
&self,
|
||||
coordinates: &Vector2<i32>,
|
||||
f: F,
|
||||
) -> Option<R> {
|
||||
self.loaded_entity_chunks
|
||||
.get(coordinates)
|
||||
.map(|x| f(x.value()))
|
||||
}
|
||||
|
||||
pub async fn get_or_fetch_entity_chunk<R, F: Fn(&SyncEntityChunk) -> R>(
|
||||
self: &Arc<Self>,
|
||||
pos: Vector2<i32>,
|
||||
f: F,
|
||||
) -> R {
|
||||
if let Some(res) = self.read_entity_chunk_sync(&pos, &f) {
|
||||
return res;
|
||||
}
|
||||
let chunk = self.get_entity_chunk(pos).await;
|
||||
f(&chunk)
|
||||
}
|
||||
|
||||
pub fn try_get_entity_chunk(
|
||||
&self,
|
||||
coordinates: Vector2<i32>,
|
||||
@ -794,17 +813,18 @@ impl Level {
|
||||
delay: u8,
|
||||
priority: TickPriority,
|
||||
) {
|
||||
let chunk = self.get_chunk(block_pos.chunk_position()).await;
|
||||
let tick_order = self.schedule_tick_counts.fetch_add(1, Ordering::Relaxed);
|
||||
chunk.block_ticks.schedule_tick(
|
||||
&ScheduledTick {
|
||||
let scheduled_tick = ScheduledTick {
|
||||
delay,
|
||||
position: block_pos,
|
||||
priority,
|
||||
value: unsafe { &*std::ptr::from_ref::<Block>(block) },
|
||||
},
|
||||
tick_order,
|
||||
);
|
||||
};
|
||||
|
||||
self.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| {
|
||||
chunk.block_ticks.schedule_tick(&scheduled_tick, tick_order);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn schedule_fluid_tick(
|
||||
@ -814,17 +834,18 @@ impl Level {
|
||||
delay: u8,
|
||||
priority: TickPriority,
|
||||
) {
|
||||
let chunk = self.get_chunk(block_pos.chunk_position()).await;
|
||||
let tick_order = self.schedule_tick_counts.fetch_add(1, Ordering::Relaxed);
|
||||
chunk.fluid_ticks.schedule_tick(
|
||||
&ScheduledTick {
|
||||
let scheduled_tick = ScheduledTick {
|
||||
delay,
|
||||
position: block_pos,
|
||||
priority,
|
||||
value: unsafe { &*std::ptr::from_ref::<Fluid>(fluid) },
|
||||
},
|
||||
tick_order,
|
||||
);
|
||||
};
|
||||
|
||||
self.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| {
|
||||
chunk.fluid_ticks.schedule_tick(&scheduled_tick, tick_order);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn is_block_tick_scheduled(
|
||||
@ -832,8 +853,10 @@ impl Level {
|
||||
block_pos: &BlockPos,
|
||||
block: &Block,
|
||||
) -> bool {
|
||||
let chunk = self.get_chunk(block_pos.chunk_position()).await;
|
||||
self.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| {
|
||||
chunk.block_ticks.is_scheduled(*block_pos, block)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn is_fluid_tick_scheduled(
|
||||
@ -841,7 +864,9 @@ impl Level {
|
||||
block_pos: &BlockPos,
|
||||
fluid: &Fluid,
|
||||
) -> bool {
|
||||
let chunk = self.get_chunk(block_pos.chunk_position()).await;
|
||||
self.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| {
|
||||
chunk.fluid_ticks.is_scheduled(*block_pos, fluid)
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,8 +454,8 @@ impl DynamicLightEngine {
|
||||
) -> Option<u8> {
|
||||
let (chunk_pos, relative) = position.chunk_and_chunk_relative_position();
|
||||
|
||||
let chunk = level.get_chunk(chunk_pos).await;
|
||||
|
||||
level
|
||||
.get_or_fetch_chunk(chunk_pos, |chunk| {
|
||||
let section_idx = (relative.y - chunk.section.min_y) as usize / 16;
|
||||
let light_engine = chunk.light_engine.lock().ok()?;
|
||||
|
||||
@ -468,6 +468,8 @@ impl DynamicLightEngine {
|
||||
relative.z as usize,
|
||||
)
|
||||
.into()
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_block_light_level(
|
||||
@ -477,8 +479,10 @@ impl DynamicLightEngine {
|
||||
light_level: u8,
|
||||
) -> Result<(), String> {
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
let chunk = level.get_chunk(chunk_coordinate).await;
|
||||
let section_index = (relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
|
||||
level
|
||||
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
|
||||
let section_index =
|
||||
(relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
|
||||
// Bounds check for section index
|
||||
let mut light_engine = chunk.light_engine.lock().unwrap();
|
||||
if section_index >= light_engine.block_light.len() {
|
||||
@ -496,12 +500,16 @@ impl DynamicLightEngine {
|
||||
chunk.mark_dirty(true);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_sky_light_level(&self, level: &Arc<Level>, position: &BlockPos) -> u8 {
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
let chunk = level.get_chunk(chunk_coordinate).await;
|
||||
let section_index = (relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
|
||||
level
|
||||
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
|
||||
let section_index =
|
||||
(relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
|
||||
|
||||
let light_engine = chunk.light_engine.lock().unwrap();
|
||||
// Bounds check for section index (lock the light engine)
|
||||
@ -514,6 +522,8 @@ impl DynamicLightEngine {
|
||||
(relative.y - chunk.section.min_y) as usize % BlockPalette::SIZE,
|
||||
relative.z as usize,
|
||||
)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_sky_light_level(
|
||||
@ -523,8 +533,10 @@ impl DynamicLightEngine {
|
||||
light_level: u8,
|
||||
) -> Result<(), String> {
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
let chunk = level.get_chunk(chunk_coordinate).await;
|
||||
let section_index = (relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
|
||||
level
|
||||
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
|
||||
let section_index =
|
||||
(relative.y - chunk.section.min_y) as usize / BlockPalette::SIZE;
|
||||
// Bounds check for section index
|
||||
let mut light_engine = chunk.light_engine.lock().unwrap();
|
||||
if section_index >= light_engine.sky_light.len() {
|
||||
@ -542,5 +554,7 @@ impl DynamicLightEngine {
|
||||
chunk.mark_dirty(true);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +67,8 @@ impl<'a> PistonHandler<'a> {
|
||||
if !self.try_move(self.pos_to, self.motion_direction).await {
|
||||
return false;
|
||||
}
|
||||
for block_pos in self.moved_blocks.clone() {
|
||||
for i in 0..self.moved_blocks.len() {
|
||||
let block_pos = self.moved_blocks[i];
|
||||
let block = self.world.get_block(&block_pos).await;
|
||||
if Self::is_block_sticky(block)
|
||||
&& !self.try_move_adjacent_block(block, &block_pos).await
|
||||
|
||||
@ -289,10 +289,13 @@ impl RedstoneWireTurbo {
|
||||
self.current_walk_layer = 1;
|
||||
|
||||
while !self.update_queue[0].is_empty() || !self.update_queue[1].is_empty() {
|
||||
for node_id in self.update_queue[0].clone() {
|
||||
let mut current_queue = self.update_queue.remove(0);
|
||||
self.update_queue.push(Vec::new());
|
||||
|
||||
for node_id in ¤t_queue {
|
||||
let block = Block::from_state_id(self.nodes[node_id.index].state.id);
|
||||
if block == &Block::REDSTONE_WIRE {
|
||||
self.update_node(world, node_id, self.current_walk_layer)
|
||||
self.update_node(world, *node_id, self.current_walk_layer)
|
||||
.await;
|
||||
} else {
|
||||
// This only works because updating any other block than a wire will
|
||||
@ -304,7 +307,10 @@ impl RedstoneWireTurbo {
|
||||
}
|
||||
}
|
||||
|
||||
self.shift_queue();
|
||||
current_queue.clear();
|
||||
let last_idx = self.update_queue.len() - 1;
|
||||
self.update_queue[last_idx] = current_queue;
|
||||
|
||||
self.current_walk_layer += 1;
|
||||
}
|
||||
|
||||
|
||||
@ -206,7 +206,7 @@ impl EntityBase for AreaEffectCloudEntity {
|
||||
#[allow(clippy::semicolon_outside_block)]
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
_caller: Arc<dyn EntityBase>,
|
||||
_caller: &'a Arc<dyn EntityBase>,
|
||||
_server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
|
||||
@ -70,12 +70,12 @@ impl NBTStorage for ExperienceOrbEntity {}
|
||||
impl EntityBase for ExperienceOrbEntity {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let entity = &self.entity;
|
||||
entity.tick(caller.clone(), server).await;
|
||||
entity.tick(caller, server).await;
|
||||
let bounding_box = entity.bounding_box.load();
|
||||
|
||||
let original_velo = entity.velocity.load();
|
||||
@ -95,9 +95,9 @@ impl EntityBase for ExperienceOrbEntity {
|
||||
|
||||
entity.velocity.store(velo);
|
||||
|
||||
entity.move_entity(caller.clone(), velo).await;
|
||||
entity.move_entity(caller, velo).await;
|
||||
|
||||
entity.tick_block_collisions(&caller, server).await;
|
||||
entity.tick_block_collisions(caller, server).await;
|
||||
|
||||
let age = self.orb_age.fetch_add(1, Ordering::Relaxed);
|
||||
if age >= 6000 {
|
||||
|
||||
@ -50,12 +50,12 @@ impl NBTStorage for FallingEntity {}
|
||||
impl EntityBase for FallingEntity {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let entity = &self.entity;
|
||||
entity.tick(caller.clone(), server).await;
|
||||
entity.tick(caller, server).await;
|
||||
|
||||
let original_velo = entity.velocity.load();
|
||||
let mut velo = original_velo;
|
||||
@ -63,8 +63,8 @@ impl EntityBase for FallingEntity {
|
||||
|
||||
entity.velocity.store(velo);
|
||||
|
||||
entity.move_entity(caller.clone(), velo).await;
|
||||
entity.tick_block_collisions(&caller, server).await;
|
||||
entity.move_entity(caller, velo).await;
|
||||
entity.tick_block_collisions(caller, server).await;
|
||||
if entity.on_ground.load(Ordering::Relaxed) {
|
||||
entity.velocity.store(velo.multiply(0.7, -0.5, 0.7));
|
||||
entity
|
||||
|
||||
@ -271,15 +271,15 @@ impl ItemEntity {
|
||||
Some(tick_move)
|
||||
}
|
||||
|
||||
async fn move_and_apply_friction(
|
||||
&self,
|
||||
caller: &Arc<dyn EntityBase>,
|
||||
server: &Server,
|
||||
async fn move_and_apply_friction<'a>(
|
||||
&'a self,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
move_velo: Vector3<f64>,
|
||||
) {
|
||||
let entity = &self.entity;
|
||||
|
||||
entity.move_entity(caller.clone(), move_velo).await;
|
||||
entity.move_entity(caller, move_velo).await;
|
||||
entity.tick_block_collisions(caller, server).await;
|
||||
|
||||
let mut friction = 0.98;
|
||||
@ -332,9 +332,9 @@ impl ItemEntity {
|
||||
true
|
||||
}
|
||||
|
||||
async fn sync_motion_if_dirty(
|
||||
&self,
|
||||
caller: &Arc<dyn EntityBase>,
|
||||
async fn sync_motion_if_dirty<'a>(
|
||||
&'a self,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
original_velo: Vector3<f64>,
|
||||
) {
|
||||
let entity = &self.entity;
|
||||
@ -358,7 +358,7 @@ impl NBTStorage for ItemEntity {}
|
||||
impl EntityBase for ItemEntity {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
@ -379,12 +379,12 @@ impl EntityBase for ItemEntity {
|
||||
};
|
||||
|
||||
if tick_move {
|
||||
self.move_and_apply_friction(&caller, server, move_velo)
|
||||
self.move_and_apply_friction(caller, server, move_velo)
|
||||
.await;
|
||||
}
|
||||
|
||||
if self.process_age_and_merge().await {
|
||||
self.sync_motion_if_dirty(&caller, original_velo).await;
|
||||
self.sync_motion_if_dirty(caller, original_velo).await;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -728,7 +728,7 @@ impl LivingEntity {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn tick_movement(&self, server: &Server, caller: Arc<dyn EntityBase>) {
|
||||
async fn tick_movement<'a>(&'a self, server: &'a Server, caller: &'a Arc<dyn EntityBase>) {
|
||||
if self.jumping_cooldown.load(Relaxed) != 0 {
|
||||
self.jumping_cooldown.fetch_sub(1, Relaxed);
|
||||
}
|
||||
@ -799,24 +799,24 @@ impl LivingEntity {
|
||||
&& should_swim_in_fluids
|
||||
&& self.entity.entity_type != &EntityType::STRIDER
|
||||
{
|
||||
self.travel_in_fluid(caller.clone(), touching_water).await;
|
||||
self.travel_in_fluid(caller, touching_water).await;
|
||||
} else {
|
||||
// TODO: Gliding
|
||||
|
||||
self.travel_in_air(caller.clone()).await;
|
||||
self.travel_in_air(caller).await;
|
||||
}
|
||||
|
||||
// TODO: Apply Soul Speed boot durability when tick_block_underneath is implemented.
|
||||
//self.entity.tick_block_underneath(&caller);
|
||||
|
||||
let suffocating = self.entity.tick_block_collisions(&caller, server).await;
|
||||
let suffocating = self.entity.tick_block_collisions(caller, server).await;
|
||||
|
||||
if suffocating {
|
||||
self.damage(&*caller, 1.0, DamageType::IN_WALL).await;
|
||||
self.damage(&**caller, 1.0, DamageType::IN_WALL).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn travel_in_air(&self, caller: Arc<dyn EntityBase>) {
|
||||
async fn travel_in_air<'a>(&'a self, caller: &'a Arc<dyn EntityBase>) {
|
||||
// applyMovementInput
|
||||
|
||||
let effective_speed = self.get_attribute_value(&Attributes::MOVEMENT_SPEED);
|
||||
@ -853,7 +853,7 @@ impl LivingEntity {
|
||||
|
||||
self.apply_climbing_speed();
|
||||
|
||||
self.make_move(caller.clone()).await;
|
||||
self.make_move(caller).await;
|
||||
|
||||
let mut velo = self.entity.velocity.load();
|
||||
|
||||
@ -874,7 +874,7 @@ impl LivingEntity {
|
||||
if let Some(lev) = levitation {
|
||||
velo.y += 0.05f64.mul_add(f64::from(lev.amplifier + 1), -velo.y) * 0.2;
|
||||
} else {
|
||||
velo.y -= self.get_effective_gravity(&caller).await;
|
||||
velo.y -= self.get_effective_gravity(caller).await;
|
||||
|
||||
// TODO: If world is not loaded: replace effective gravity with:
|
||||
|
||||
@ -898,11 +898,11 @@ impl LivingEntity {
|
||||
self.entity.velocity.store(velo);
|
||||
}
|
||||
|
||||
async fn travel_in_fluid(&self, caller: Arc<dyn EntityBase>, water: bool) {
|
||||
async fn travel_in_fluid<'a>(&'a self, caller: &'a Arc<dyn EntityBase>, water: bool) {
|
||||
let movement_input = self.movement_input.load();
|
||||
|
||||
let falling = self.entity.velocity.load().y <= 0.0;
|
||||
let gravity = self.get_effective_gravity(&caller).await;
|
||||
let gravity = self.get_effective_gravity(caller).await;
|
||||
let effective_speed = self.get_attribute_value(&Attributes::MOVEMENT_SPEED);
|
||||
|
||||
if water {
|
||||
@ -995,7 +995,7 @@ impl LivingEntity {
|
||||
}
|
||||
}
|
||||
|
||||
async fn make_move(&self, caller: Arc<dyn EntityBase>) {
|
||||
async fn make_move<'a>(&'a self, caller: &'a Arc<dyn EntityBase>) {
|
||||
self.entity
|
||||
.move_entity(caller, self.entity.velocity.load())
|
||||
.await;
|
||||
@ -2028,11 +2028,11 @@ impl EntityBase for LivingEntity {
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
self.entity.tick(caller.clone(), server).await;
|
||||
self.entity.tick(caller, server).await;
|
||||
|
||||
// Only tick movement if the entity is alive. This prevents a dead "corpse"
|
||||
// from continuing to be simulated (accumulating fall_distance/velocity).
|
||||
@ -2041,7 +2041,7 @@ impl EntityBase for LivingEntity {
|
||||
let in_death_animation =
|
||||
self.health.load() <= 0.0 && self.death_time.load(Relaxed) < 20;
|
||||
if is_alive || (in_death_animation && self.entity.entity_type != &EntityType::PLAYER) {
|
||||
self.tick_movement(server, caller.clone()).await;
|
||||
self.tick_movement(server, caller).await;
|
||||
// Vanilla-like order: freeze logic runs after movement/collisions.
|
||||
self.entity.tick_frozen(caller.as_ref()).await;
|
||||
}
|
||||
|
||||
@ -306,11 +306,10 @@ pub trait Mob: EntityBase + Send + Sync {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Mob + Send + 'static> EntityBase for T {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
@ -319,11 +318,12 @@ impl<T: Mob + Send + 'static> EntityBase for T {
|
||||
if mob_entity.breeding_cooldown.load(Relaxed) > 0 {
|
||||
mob_entity.breeding_cooldown.fetch_sub(1, Relaxed);
|
||||
}
|
||||
|
||||
if mob_entity.love_ticks.load(Relaxed) > 0 {
|
||||
mob_entity.love_ticks.fetch_sub(1, Relaxed);
|
||||
}
|
||||
|
||||
self.mob_tick(&caller).await;
|
||||
self.mob_tick(caller).await;
|
||||
|
||||
// AI runs before physics (vanilla order: goals → navigator → look → physics)
|
||||
let age = mob_entity.living_entity.entity.age.load(Relaxed);
|
||||
|
||||
@ -117,7 +117,7 @@ pub trait EntityBase: Send + Sync + NBTStorage + std::any::Any {
|
||||
/// The `server` parameter provides access to the game server instance.
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
@ -1508,7 +1508,7 @@ impl Entity {
|
||||
// Move by a delta, adjust for collisions, and send
|
||||
|
||||
// Does not send movement. That must be done separately
|
||||
async fn move_entity(&self, caller: Arc<dyn EntityBase>, mut motion: Vector3<f64>) {
|
||||
async fn move_entity<'a>(&'a self, caller: &'a Arc<dyn EntityBase>, mut motion: Vector3<f64>) {
|
||||
if caller.get_player().is_some() {
|
||||
return;
|
||||
}
|
||||
@ -2753,7 +2753,7 @@ impl NBTStorage for Entity {
|
||||
impl EntityBase for Entity {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
_server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
@ -2763,9 +2763,9 @@ impl EntityBase for Entity {
|
||||
.store(was_in_powder_snow, Ordering::Relaxed);
|
||||
self.is_in_powder_snow.store(false, Ordering::Relaxed);
|
||||
self.update_last_pos();
|
||||
self.tick_portal(&caller).await;
|
||||
self.update_fluid_state(&caller).await;
|
||||
self.check_out_of_world(&*caller).await;
|
||||
self.tick_portal(caller).await;
|
||||
self.update_fluid_state(caller).await;
|
||||
self.check_out_of_world(&**caller).await;
|
||||
let fire_ticks = self.fire_ticks.load(Ordering::Relaxed);
|
||||
|
||||
// Check for fire immunity (or if the specific entity is)
|
||||
@ -2779,7 +2779,7 @@ impl EntityBase for Entity {
|
||||
}
|
||||
} else {
|
||||
if fire_ticks % 20 == 0 {
|
||||
caller.damage(&*caller, 1.0, DamageType::ON_FIRE).await;
|
||||
(**caller).damage(&**caller, 1.0, DamageType::ON_FIRE).await;
|
||||
}
|
||||
|
||||
self.fire_ticks.store(fire_ticks - 1, Ordering::Relaxed);
|
||||
|
||||
@ -1597,7 +1597,8 @@ impl Player {
|
||||
|
||||
self.last_attacked_ticks.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
self.living_entity.tick(self.clone(), server).await;
|
||||
let caller: Arc<dyn EntityBase> = self.clone();
|
||||
self.living_entity.tick(&caller, server).await;
|
||||
// Vanilla updates pose in PlayerEntity#tick after super.tick().
|
||||
self.update_player_pose().await;
|
||||
self.breath_manager.tick(self).await;
|
||||
|
||||
@ -191,7 +191,7 @@ impl EntityBase for ArrowEntity {
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
_server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
|
||||
@ -86,7 +86,7 @@ impl EntityBase for EggEntity {
|
||||
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move { self.thrown.process_tick(caller, server).await })
|
||||
|
||||
@ -43,7 +43,7 @@ impl NBTStorage for EnderPearlEntity {}
|
||||
impl EntityBase for EnderPearlEntity {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move { self.thrown.process_tick(caller, server).await })
|
||||
|
||||
@ -123,7 +123,7 @@ impl NBTStorage for EyeOfEnder {}
|
||||
impl EntityBase for EyeOfEnder {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
|
||||
@ -103,7 +103,7 @@ impl NBTStorage for FireworkRocketEntity {}
|
||||
impl EntityBase for FireworkRocketEntity {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
|
||||
@ -82,7 +82,7 @@ impl EntityBase for LingeringPotionEntity {
|
||||
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move { self.thrown.process_tick(caller, server).await })
|
||||
|
||||
@ -103,7 +103,7 @@ impl NBTStorage for ThrownItemEntity {}
|
||||
|
||||
impl ThrownItemEntity {
|
||||
/// Process a tick for projectile movement and collisions
|
||||
pub async fn process_tick(&self, caller: Arc<dyn EntityBase>, _server: &Server) {
|
||||
pub async fn process_tick<'a>(&'a self, caller: &'a Arc<dyn EntityBase>, _server: &'a Server) {
|
||||
let entity = self.get_entity();
|
||||
let world = entity.world.load();
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ impl NBTStorage for SnowballEntity {}
|
||||
impl EntityBase for SnowballEntity {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move { self.thrown.process_tick(caller, server).await })
|
||||
|
||||
@ -123,7 +123,7 @@ impl EntityBase for SplashPotionEntity {
|
||||
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move { self.thrown.process_tick(caller, server).await })
|
||||
|
||||
@ -75,7 +75,7 @@ impl NBTStorage for WindChargeEntity {}
|
||||
impl EntityBase for WindChargeEntity {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
|
||||
@ -36,7 +36,7 @@ impl NBTStorage for TNTEntity {}
|
||||
impl EntityBase for TNTEntity {
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
caller: Arc<dyn EntityBase>,
|
||||
caller: &'a Arc<dyn EntityBase>,
|
||||
server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
@ -46,8 +46,8 @@ impl EntityBase for TNTEntity {
|
||||
let mut velo = original_velo;
|
||||
velo.y -= self.get_gravity();
|
||||
|
||||
entity.move_entity(caller.clone(), velo).await;
|
||||
entity.tick_block_collisions(&caller, server).await;
|
||||
entity.move_entity(caller, velo).await;
|
||||
entity.tick_block_collisions(caller, server).await;
|
||||
entity.velocity.store(velo.multiply(0.98, 0.98, 0.98));
|
||||
|
||||
if entity.on_ground.load(Ordering::Relaxed) {
|
||||
@ -73,7 +73,7 @@ impl EntityBase for TNTEntity {
|
||||
} else {
|
||||
// Safe decrement
|
||||
self.fuse.store(fuse - 1, Relaxed);
|
||||
entity.update_fluid_state(&caller).await;
|
||||
entity.update_fluid_state(caller).await;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ impl EntityBase for BoatEntity {
|
||||
|
||||
fn tick<'a>(
|
||||
&'a self,
|
||||
_caller: Arc<dyn EntityBase>,
|
||||
_caller: &'a Arc<dyn EntityBase>,
|
||||
_server: &'a Server,
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
|
||||
@ -1197,9 +1197,6 @@ impl JavaClient {
|
||||
return;
|
||||
};
|
||||
|
||||
let inventory = player.inventory();
|
||||
let item = inventory.held_item();
|
||||
|
||||
let (yaw, pitch) = player.rotation();
|
||||
let hit_result = player
|
||||
.world()
|
||||
@ -1219,18 +1216,11 @@ impl JavaClient {
|
||||
PlayerInteractEvent::new(
|
||||
player,
|
||||
InteractAction::LeftClickBlock,
|
||||
&item,
|
||||
player.world().get_block(&hit_pos).await,
|
||||
Some(hit_pos),
|
||||
)
|
||||
} else {
|
||||
PlayerInteractEvent::new(
|
||||
player,
|
||||
InteractAction::LeftClickAir,
|
||||
&item,
|
||||
&Block::AIR,
|
||||
None,
|
||||
)
|
||||
PlayerInteractEvent::new(player, InteractAction::LeftClickAir, &Block::AIR, None)
|
||||
};
|
||||
|
||||
let server = player.world().server.upgrade().unwrap();
|
||||
@ -2264,18 +2254,11 @@ impl JavaClient {
|
||||
PlayerInteractEvent::new(
|
||||
player,
|
||||
InteractAction::RightClickBlock,
|
||||
&item_in_hand,
|
||||
player.world().get_block(&hit_pos).await,
|
||||
Some(hit_pos),
|
||||
)
|
||||
} else {
|
||||
PlayerInteractEvent::new(
|
||||
player,
|
||||
InteractAction::RightClickAir,
|
||||
&item_in_hand,
|
||||
&Block::AIR,
|
||||
None,
|
||||
)
|
||||
PlayerInteractEvent::new(player, InteractAction::RightClickAir, &Block::AIR, None)
|
||||
};
|
||||
self.prepare_hand_item_for_use(player, hand, &item_in_hand)
|
||||
.await;
|
||||
|
||||
@ -2,10 +2,8 @@ use std::sync::Arc;
|
||||
|
||||
use crate::entity::player::Player;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::item_stack::ItemStack;
|
||||
use pumpkin_macros::{Event, cancellable};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use super::PlayerEvent;
|
||||
|
||||
@ -26,9 +24,6 @@ pub struct PlayerInteractEvent {
|
||||
/// The position of the block that was clicked, if any.
|
||||
pub clicked_pos: Option<BlockPos>,
|
||||
|
||||
/// The item in the player's hand at the time of interaction.
|
||||
pub item: Arc<Mutex<ItemStack>>,
|
||||
|
||||
/// The block that was interacted with.
|
||||
pub block: &'static Block,
|
||||
}
|
||||
@ -50,14 +45,12 @@ impl PlayerInteractEvent {
|
||||
pub fn new(
|
||||
player: &Arc<Player>,
|
||||
action: InteractAction,
|
||||
item: &Arc<Mutex<ItemStack>>,
|
||||
block: &'static Block,
|
||||
clicked_pos: Option<BlockPos>,
|
||||
) -> Self {
|
||||
Self {
|
||||
player: Arc::clone(player),
|
||||
action,
|
||||
item: Arc::clone(item),
|
||||
block,
|
||||
clicked_pos,
|
||||
cancelled: false,
|
||||
|
||||
@ -576,22 +576,10 @@ impl ToFromWasmEvent for PlayerInteractEvent {
|
||||
.add_player(self.player.clone())
|
||||
.expect("failed to add player resource");
|
||||
|
||||
let stack = self.item.blocking_lock();
|
||||
let item = crate::plugin::loader::wasm::wasm_host::wit::v0_1::player::to_wit_item_stack(
|
||||
&stack,
|
||||
)
|
||||
.unwrap_or(
|
||||
crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::common::ItemStack {
|
||||
registry_key: "minecraft:air".to_string(),
|
||||
count: 0,
|
||||
},
|
||||
);
|
||||
|
||||
Event::PlayerInteractEvent(PlayerInteractEventData {
|
||||
player,
|
||||
action: to_wasm_interact_action(&self.action),
|
||||
clicked_pos: self.clicked_pos.map(to_wasm_block_position),
|
||||
item,
|
||||
block: self.block.name.to_string(),
|
||||
cancelled: self.cancelled,
|
||||
})
|
||||
|
||||
@ -300,6 +300,7 @@ impl World {
|
||||
entity.write_nbt(&mut nbt).await;
|
||||
if let Some(old_chunk) = base_entity.first_loaded_chunk_position.load() {
|
||||
let old_chunk = old_chunk.to_vec2_i32();
|
||||
|
||||
let chunk = self.level.get_entity_chunk(old_chunk).await;
|
||||
chunk.mark_dirty(true);
|
||||
let mut data = chunk.data.lock().await;
|
||||
@ -776,7 +777,7 @@ impl World {
|
||||
|
||||
for entity in entities_to_tick.iter() {
|
||||
entity.get_entity().age.fetch_add(1, Relaxed);
|
||||
entity.tick(entity.clone(), server).await;
|
||||
entity.tick(entity, server).await;
|
||||
|
||||
for player in players.iter() {
|
||||
if player
|
||||
@ -989,12 +990,14 @@ impl World {
|
||||
)
|
||||
};
|
||||
let spawn_passives = self.level_time.lock().await.time_of_day % 400 == 0;
|
||||
let spawn_enemies = !peaceful && spawn_monsters && spawn_mobs;
|
||||
let spawn_passives = spawn_passives && spawn_mobs;
|
||||
let spawn_list: Vec<&'static MobCategory> =
|
||||
natural_spawner::get_filtered_spawning_categories(
|
||||
&spawn_state,
|
||||
spawn_mobs,
|
||||
peaceful && spawn_mobs && spawn_monsters,
|
||||
peaceful && spawn_mobs && spawn_passives && spawn_monsters,
|
||||
spawn_enemies,
|
||||
spawn_passives,
|
||||
);
|
||||
|
||||
// log::debug!("spawning list size {}", spawn_list.len());
|
||||
@ -1454,12 +1457,15 @@ impl World {
|
||||
/// Gets the `MOTION_BLOCKING` heightmap value for a given XZ position.
|
||||
pub async fn get_motion_blocking_height(&self, x: i32, z: i32) -> i32 {
|
||||
let chunk_pos = Vector2::new(x >> 4, z >> 4);
|
||||
let chunk = self.level.get_chunk(chunk_pos).await;
|
||||
self.level
|
||||
.get_or_fetch_chunk(chunk_pos, |chunk| {
|
||||
chunk
|
||||
.heightmap
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(MotionBlocking, x, z, self.min_y)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
@ -2388,7 +2394,10 @@ impl World {
|
||||
// Ensure at least the center chunk is sent synchronously before teleport.
|
||||
if let crate::net::ClientPlatform::Java(java_client) = &player.client {
|
||||
let center_chunk = player.living_entity.entity.chunk_pos.load();
|
||||
let chunk = target_world.level.get_chunk(center_chunk).await;
|
||||
let chunk = target_world
|
||||
.level
|
||||
.get_or_fetch_chunk(center_chunk, std::clone::Clone::clone)
|
||||
.await;
|
||||
java_client.send_packet_now(&CChunkBatchStart).await;
|
||||
java_client.send_packet_now(&CChunkData(&chunk)).await;
|
||||
java_client
|
||||
@ -2520,14 +2529,18 @@ impl World {
|
||||
|
||||
let mut data = chunk.data.lock().await;
|
||||
if old_chunk == current_chunk_coordinate {
|
||||
data.insert(base_entity.entity_uuid, nbt);
|
||||
data.insert(base_entity.entity_uuid, nbt.clone());
|
||||
return;
|
||||
}
|
||||
|
||||
// The chunk has changed, lets remove the entity from the old chunk
|
||||
data.remove(&base_entity.entity_uuid);
|
||||
}
|
||||
chunk.data.lock().await.insert(base_entity.entity_uuid, nbt);
|
||||
chunk
|
||||
.data
|
||||
.lock()
|
||||
.await
|
||||
.insert(base_entity.entity_uuid, nbt.clone());
|
||||
chunk.mark_dirty(true);
|
||||
}
|
||||
|
||||
@ -3000,13 +3013,12 @@ impl World {
|
||||
pub async fn add_entity_silent(&self, entity: Arc<dyn EntityBase>) {
|
||||
let base_entity = entity.get_entity();
|
||||
let chunk_coordinate = base_entity.block_pos.load().chunk_position();
|
||||
let chunk = self.level.get_entity_chunk(chunk_coordinate).await;
|
||||
{
|
||||
let mut nbt = PNbtCompound::new();
|
||||
entity.write_nbt(&mut nbt).await;
|
||||
|
||||
let chunk = self.level.get_entity_chunk(chunk_coordinate).await;
|
||||
chunk.data.lock().await.insert(base_entity.entity_uuid, nbt);
|
||||
chunk.mark_dirty(true);
|
||||
};
|
||||
|
||||
self.entities.rcu(|current_entities| {
|
||||
let mut new_entities = (**current_entities).clone();
|
||||
@ -3048,23 +3060,26 @@ impl World {
|
||||
flags: BlockFlags,
|
||||
) -> BlockStateId {
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
let level = &self.level;
|
||||
let chunk = level.get_chunk(chunk_coordinate).await;
|
||||
|
||||
let replaced_block_state_id = self
|
||||
.level
|
||||
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
|
||||
let replaced_block_state_id = chunk.section.set_block_absolute_y(
|
||||
relative.x as usize,
|
||||
relative.y,
|
||||
relative.z as usize,
|
||||
block_state_id,
|
||||
);
|
||||
// Mark chunk dirty if it isn't already
|
||||
if replaced_block_state_id != block_state_id && !chunk.is_dirty() {
|
||||
chunk.mark_dirty(true);
|
||||
}
|
||||
replaced_block_state_id
|
||||
})
|
||||
.await;
|
||||
|
||||
if replaced_block_state_id == block_state_id {
|
||||
return block_state_id;
|
||||
}
|
||||
// Mark chunk dirty if it isn't already
|
||||
if !chunk.is_dirty() {
|
||||
chunk.mark_dirty(true);
|
||||
}
|
||||
drop(chunk);
|
||||
|
||||
self.unsent_block_changes
|
||||
.lock()
|
||||
@ -3172,9 +3187,9 @@ impl World {
|
||||
|
||||
let (_chunk_coordinate, _) = position.chunk_and_chunk_relative_position();
|
||||
|
||||
level
|
||||
self.level
|
||||
.light_engine
|
||||
.update_lighting_at(level, *position)
|
||||
.update_lighting_at(&self.level, *position)
|
||||
.await;
|
||||
|
||||
replaced_block_state_id
|
||||
@ -3660,19 +3675,21 @@ impl World {
|
||||
}
|
||||
|
||||
pub async fn get_block_entity(&self, block_pos: &BlockPos) -> Option<Arc<dyn BlockEntity>> {
|
||||
let chunk = self.level.get_chunk(block_pos.chunk_position()).await;
|
||||
self.level
|
||||
.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| {
|
||||
chunk.block_entities.lock().unwrap().get(block_pos).cloned()
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn add_block_entity(&self, block_entity: Arc<dyn BlockEntity>) {
|
||||
let block_pos = block_entity.get_position();
|
||||
let chunk = self.level.get_chunk(block_pos.chunk_position()).await;
|
||||
let chunk_pos = block_pos.chunk_position();
|
||||
let block_entity_nbt = block_entity.chunk_data_nbt();
|
||||
|
||||
if let Some(nbt) = &block_entity_nbt {
|
||||
let mut bytes = Vec::new();
|
||||
to_bytes_unnamed(nbt, &mut bytes).unwrap();
|
||||
let chunk_pos = block_pos.chunk_position();
|
||||
self.broadcast_to_chunk(
|
||||
chunk_pos,
|
||||
&CBlockEntityData::new(
|
||||
@ -3684,16 +3701,21 @@ impl World {
|
||||
.await;
|
||||
}
|
||||
|
||||
self.level
|
||||
.get_or_fetch_chunk(chunk_pos, |chunk| {
|
||||
chunk
|
||||
.block_entities
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(block_pos, block_entity);
|
||||
.insert(block_pos, block_entity.clone());
|
||||
chunk.mark_dirty(true);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn remove_block_entity(&self, block_pos: &BlockPos) {
|
||||
let chunk = self.level.get_chunk(block_pos.chunk_position()).await;
|
||||
self.level
|
||||
.get_or_fetch_chunk(block_pos.chunk_position(), |chunk| {
|
||||
if chunk
|
||||
.block_entities
|
||||
.lock()
|
||||
@ -3703,17 +3725,18 @@ impl World {
|
||||
{
|
||||
chunk.mark_dirty(true);
|
||||
}
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn update_block_entity(&self, block_entity: &Arc<dyn BlockEntity>) {
|
||||
let block_pos = block_entity.get_position();
|
||||
let chunk = self.level.get_chunk(block_pos.chunk_position()).await;
|
||||
let chunk_pos = block_pos.chunk_position();
|
||||
let block_entity_nbt = block_entity.chunk_data_nbt();
|
||||
|
||||
if let Some(nbt) = &block_entity_nbt {
|
||||
let mut bytes = Vec::new();
|
||||
to_bytes_unnamed(nbt, &mut bytes).unwrap();
|
||||
let chunk_pos = block_pos.chunk_position();
|
||||
self.broadcast_to_chunk(
|
||||
chunk_pos,
|
||||
&CBlockEntityData::new(
|
||||
@ -3724,7 +3747,11 @@ impl World {
|
||||
)
|
||||
.await;
|
||||
}
|
||||
self.level
|
||||
.get_or_fetch_chunk(chunk_pos, |chunk| {
|
||||
chunk.mark_dirty(true);
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
fn intersects_aabb_with_direction(
|
||||
|
||||
@ -434,7 +434,6 @@ pub async fn spawn_category_for_position(
|
||||
prepared_data.push((base_entity.entity_uuid, nbt, packet, entity.clone()));
|
||||
}
|
||||
|
||||
{
|
||||
let chunk_handle = world.level.get_entity_chunk(*chunk_pos).await;
|
||||
let mut data = chunk_handle.data.lock().await;
|
||||
|
||||
@ -457,7 +456,6 @@ pub async fn spawn_category_for_position(
|
||||
}
|
||||
new_entities
|
||||
});
|
||||
};
|
||||
|
||||
for (_, _, packet, _) in prepared_data {
|
||||
world.broadcast_packet_all(&packet).await;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user