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