refactor(block-entities): from async to sync Part 4
This commit is contained in:
parent
52038e3356
commit
e2a138cfa6
@ -196,21 +196,13 @@ impl BlockBehaviour for BedBlock {
|
||||
}
|
||||
|
||||
fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
let player = Arc::clone(args.player);
|
||||
let world = Arc::clone(args.world);
|
||||
let block_id = args.block.id;
|
||||
let position = *args.position;
|
||||
tokio::spawn(async move {
|
||||
let block = Block::from_id(block_id);
|
||||
Self::use_bed(&world, &player, block, &position).await;
|
||||
});
|
||||
BlockActionResult::SuccessServer
|
||||
Self::use_bed(args.world, args.player, args.block, args.position)
|
||||
}
|
||||
}
|
||||
|
||||
impl BedBlock {
|
||||
#[expect(clippy::too_many_lines)]
|
||||
async fn use_bed(
|
||||
fn use_bed(
|
||||
world: &Arc<World>,
|
||||
player: &Arc<Player>,
|
||||
block: &Block,
|
||||
@ -341,7 +333,7 @@ impl BedBlock {
|
||||
player.clone(),
|
||||
bed_head_pos,
|
||||
);
|
||||
server.plugin_manager.fire(&server, &mut event).await;
|
||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||
if event.cancelled {
|
||||
return BlockActionResult::SuccessServer;
|
||||
}
|
||||
|
||||
@ -30,11 +30,18 @@ impl BrushableBlock {
|
||||
if let Some(be) = world.get_block_entity(pos)
|
||||
&& let Some(brush_be) = be.as_any().downcast_ref::<BrushableBlockBlockEntity>()
|
||||
{
|
||||
let mut hits = brush_be.hits.lock().await;
|
||||
let mut hits = brush_be
|
||||
.hits
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
*hits += 1;
|
||||
|
||||
if *hits >= 4 {
|
||||
let item = brush_be.item.lock().await.take();
|
||||
let item = brush_be
|
||||
.item
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.take();
|
||||
if let Some(item_stack) = item {
|
||||
world.drop_stack(pos, item_stack);
|
||||
}
|
||||
@ -84,7 +91,11 @@ impl BlockBehaviour for BrushableBlock {
|
||||
fn broken(&self, args: BrokenArgs<'_>) {
|
||||
if let Some(be) = args.world.get_block_entity(args.position)
|
||||
&& let Some(brush_be) = be.as_any().downcast_ref::<BrushableBlockBlockEntity>()
|
||||
&& let Some(contained) = brush_be.item.blocking_lock().take()
|
||||
&& let Some(contained) = brush_be
|
||||
.item
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.take()
|
||||
{
|
||||
args.world.drop_stack(args.position, contained);
|
||||
}
|
||||
|
||||
@ -174,30 +174,27 @@ impl BlockBehaviour for DispenserBlock {
|
||||
}
|
||||
|
||||
fn on_scheduled_tick(&self, args: OnScheduledTickArgs<'_>) {
|
||||
let world = args.world.clone();
|
||||
let position = *args.position;
|
||||
tokio::spawn(async move {
|
||||
let (block, state) = world.get_block_and_state(&position);
|
||||
if let Some(block_entity) = world.get_block_entity(&position) {
|
||||
let Some(dispenser) = block_entity.as_any().downcast_ref::<DispenserBlockEntity>()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let (block, state) = args.world.get_block_and_state(args.position);
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position) {
|
||||
let Some(dispenser) = block_entity.as_any().downcast_ref::<DispenserBlockEntity>()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some((slot_index, mut item)) = dispenser.get_random_slot() {
|
||||
let props = DispenserLikeProperties::from_state_id(state.id, block);
|
||||
let ctx = DispenseContext {
|
||||
world: &world,
|
||||
position: &position,
|
||||
facing: props.facing,
|
||||
};
|
||||
Self::dispense(&ctx, dispenser, &mut item).await;
|
||||
dispenser.set_stack(slot_index, item);
|
||||
} else {
|
||||
world.sync_world_event(WorldEvent::SoundDispenserFail, position, 0);
|
||||
}
|
||||
if let Some((slot_index, mut item)) = dispenser.get_random_slot() {
|
||||
let props = DispenserLikeProperties::from_state_id(state.id, block);
|
||||
let ctx = DispenseContext {
|
||||
world: args.world,
|
||||
position: args.position,
|
||||
facing: props.facing,
|
||||
};
|
||||
Self::dispense(&ctx, dispenser, &mut item);
|
||||
dispenser.set_stack(slot_index, item);
|
||||
} else {
|
||||
args.world
|
||||
.sync_world_event(WorldEvent::SoundDispenserFail, *args.position, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn get_comparator_output(&self, args: GetComparatorOutputArgs<'_>) -> Option<u8> {
|
||||
@ -225,17 +222,13 @@ impl DispenserBlock {
|
||||
const FIREWORK_PROJECTILE_POWER: f64 = 0.5;
|
||||
const FIREWORK_PROJECTILE_UNCERTAINTY: f64 = 1.0;
|
||||
|
||||
async fn dispense(
|
||||
ctx: &DispenseContext<'_>,
|
||||
dispenser: &DispenserBlockEntity,
|
||||
item: &mut ItemStack,
|
||||
) {
|
||||
fn dispense(ctx: &DispenseContext<'_>, dispenser: &DispenserBlockEntity, item: &mut ItemStack) {
|
||||
let mut event = crate::plugin::api::events::block::block_dispense::BlockDispenseEvent::new(
|
||||
*ctx.position,
|
||||
item.item.registry_key.to_string(),
|
||||
);
|
||||
if let Some(server) = ctx.world.server.upgrade() {
|
||||
server.plugin_manager.fire(&server, &mut event).await;
|
||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||
}
|
||||
if event.cancelled {
|
||||
ctx.world
|
||||
|
||||
@ -135,73 +135,72 @@ impl BlockBehaviour for DropperBlock {
|
||||
}
|
||||
|
||||
fn on_scheduled_tick(&self, args: OnScheduledTickArgs<'_>) {
|
||||
let world = args.world.clone();
|
||||
let position = *args.position;
|
||||
tokio::spawn(async move {
|
||||
let (block, state) = world.get_block_and_state(&position);
|
||||
if let Some(block_entity) = world.get_block_entity(&position) {
|
||||
let Some(dropper) = block_entity.as_any().downcast_ref::<DropperBlockEntity>()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let (block, state) = args.world.get_block_and_state(args.position);
|
||||
if let Some(block_entity) = args.world.get_block_entity(args.position) {
|
||||
let Some(dropper) = block_entity.as_any().downcast_ref::<DropperBlockEntity>() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some((slot_index, mut item)) = dropper.get_random_slot() {
|
||||
let props = DispenserLikeProperties::from_state_id(state.id, block);
|
||||
if let Some((slot_index, mut item)) = dropper.get_random_slot() {
|
||||
let props = DispenserLikeProperties::from_state_id(state.id, block);
|
||||
|
||||
let target_pos = position.offset(props.facing.to_block_direction().to_offset());
|
||||
let target_pos = args
|
||||
.position
|
||||
.offset(props.facing.to_block_direction().to_offset());
|
||||
|
||||
if let Some(entity) = world.get_block_entity(&target_pos)
|
||||
&& let Some(container) = entity.get_inventory()
|
||||
{
|
||||
let backup = item.clone();
|
||||
let one_item = item.split(1);
|
||||
if let Some(entity) = args.world.get_block_entity(&target_pos)
|
||||
&& let Some(container) = entity.get_inventory()
|
||||
{
|
||||
let backup = item.clone();
|
||||
let one_item = item.split(1);
|
||||
|
||||
if HopperBlockEntity::add_one_item(dropper, container.as_ref(), &one_item) {
|
||||
dropper.set_stack(slot_index, item);
|
||||
return;
|
||||
}
|
||||
|
||||
dropper.set_stack(slot_index, backup);
|
||||
if HopperBlockEntity::add_one_item(dropper, container.as_ref(), &one_item) {
|
||||
dropper.set_stack(slot_index, item);
|
||||
return;
|
||||
}
|
||||
|
||||
// No container found, dispense item into the world
|
||||
let drop_item = item.split(1);
|
||||
dropper.set_stack(slot_index, item);
|
||||
let facing = to_normal(props.facing);
|
||||
let mut pos = position.to_centered_f64().add(&(facing * 0.7));
|
||||
|
||||
pos.y -= match props.facing {
|
||||
Facing::Up | Facing::Down => 0.125,
|
||||
_ => 0.15625,
|
||||
};
|
||||
|
||||
let entity = Entity::new(world.clone(), pos, &EntityType::ITEM);
|
||||
let rd = rng().random::<f64>().mul_add(0.1, 0.2);
|
||||
|
||||
let velocity = Vector3::new(
|
||||
triangle(&mut rng(), facing.x * rd, 0.017_227_5 * 6.),
|
||||
triangle(&mut rng(), 0.2, 0.017_227_5 * 6.),
|
||||
triangle(&mut rng(), facing.z * rd, 0.017_227_5 * 6.),
|
||||
);
|
||||
|
||||
let item_entity = Arc::new(ItemEntity::new_with_velocity(
|
||||
entity, drop_item, velocity, 40,
|
||||
));
|
||||
world.spawn_entity(item_entity);
|
||||
|
||||
world.sync_world_event(WorldEvent::SoundDispenserDispense, position, 0);
|
||||
|
||||
world.sync_world_event(
|
||||
WorldEvent::ParticlesShootSmoke,
|
||||
position,
|
||||
to_data3d(props.facing),
|
||||
);
|
||||
} else {
|
||||
world.sync_world_event(WorldEvent::SoundDispenserDispense, position, 0);
|
||||
dropper.set_stack(slot_index, backup);
|
||||
return;
|
||||
}
|
||||
|
||||
// No container found, dispense item into the world
|
||||
let drop_item = item.split(1);
|
||||
dropper.set_stack(slot_index, item);
|
||||
let facing = to_normal(props.facing);
|
||||
let mut pos = args.position.to_centered_f64().add(&(facing * 0.7));
|
||||
|
||||
pos.y -= match props.facing {
|
||||
Facing::Up | Facing::Down => 0.125,
|
||||
_ => 0.15625,
|
||||
};
|
||||
|
||||
let entity = Entity::new(args.world.clone(), pos, &EntityType::ITEM);
|
||||
let rd = rng().random::<f64>().mul_add(0.1, 0.2);
|
||||
|
||||
let velocity = Vector3::new(
|
||||
triangle(&mut rng(), facing.x * rd, 0.017_227_5 * 6.),
|
||||
triangle(&mut rng(), 0.2, 0.017_227_5 * 6.),
|
||||
triangle(&mut rng(), facing.z * rd, 0.017_227_5 * 6.),
|
||||
);
|
||||
|
||||
let item_entity = Arc::new(ItemEntity::new_with_velocity(
|
||||
entity, drop_item, velocity, 40,
|
||||
));
|
||||
args.world.spawn_entity(item_entity);
|
||||
|
||||
args.world
|
||||
.sync_world_event(WorldEvent::SoundDispenserDispense, *args.position, 0);
|
||||
|
||||
args.world.sync_world_event(
|
||||
WorldEvent::ParticlesShootSmoke,
|
||||
*args.position,
|
||||
to_data3d(props.facing),
|
||||
);
|
||||
} else {
|
||||
args.world
|
||||
.sync_world_event(WorldEvent::SoundDispenserDispense, *args.position, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn get_comparator_output(&self, args: GetComparatorOutputArgs<'_>) -> Option<u8> {
|
||||
|
||||
@ -41,52 +41,56 @@ impl BlockBehaviour for RepeaterBlock {
|
||||
}
|
||||
|
||||
fn on_scheduled_tick(&self, args: OnScheduledTickArgs<'_>) {
|
||||
let world = args.world.clone();
|
||||
let pos = *args.position;
|
||||
tokio::spawn(async move {
|
||||
let (block, state) = world.get_block_and_state(&pos);
|
||||
if Self.is_locked(&world, pos, state.id, block) {
|
||||
return;
|
||||
}
|
||||
let mut props = RepeaterProperties::from_state_id(state.id, block);
|
||||
let (block, state) = args.world.get_block_and_state(args.position);
|
||||
if self.is_locked(args.world, *args.position, state.id, block) {
|
||||
return;
|
||||
}
|
||||
let mut props = RepeaterProperties::from_state_id(state.id, block);
|
||||
|
||||
let now_powered = props.powered;
|
||||
let should_be_powered = Self.has_power(&world, pos, state, block);
|
||||
let now_powered = props.powered;
|
||||
let should_be_powered = self.has_power(args.world, *args.position, state, block);
|
||||
|
||||
if now_powered && !should_be_powered {
|
||||
props.powered = false;
|
||||
world.set_block_state(&pos, props.to_state_id(block), BlockFlags::NOTIFY_LISTENERS);
|
||||
RedstoneGateBlock::update_target(
|
||||
&Self,
|
||||
&world,
|
||||
pos,
|
||||
props.to_state_id(block),
|
||||
if now_powered && !should_be_powered {
|
||||
props.powered = false;
|
||||
args.world.set_block_state(
|
||||
args.position,
|
||||
props.to_state_id(block),
|
||||
BlockFlags::NOTIFY_LISTENERS,
|
||||
);
|
||||
RedstoneGateBlock::update_target(
|
||||
self,
|
||||
args.world,
|
||||
*args.position,
|
||||
props.to_state_id(block),
|
||||
block,
|
||||
);
|
||||
} else if !now_powered {
|
||||
props.powered = true;
|
||||
args.world.set_block_state(
|
||||
args.position,
|
||||
props.to_state_id(block),
|
||||
BlockFlags::NOTIFY_LISTENERS,
|
||||
);
|
||||
if !should_be_powered {
|
||||
args.world.schedule_block_tick(
|
||||
block,
|
||||
);
|
||||
} else if !now_powered {
|
||||
props.powered = true;
|
||||
world.set_block_state(&pos, props.to_state_id(block), BlockFlags::NOTIFY_LISTENERS);
|
||||
if !should_be_powered {
|
||||
world.schedule_block_tick(
|
||||
*args.position,
|
||||
RedstoneGateBlock::get_update_delay_internal(
|
||||
self,
|
||||
props.to_state_id(block),
|
||||
block,
|
||||
pos,
|
||||
RedstoneGateBlock::get_update_delay_internal(
|
||||
&Self,
|
||||
props.to_state_id(block),
|
||||
block,
|
||||
),
|
||||
TickPriority::VeryHigh,
|
||||
);
|
||||
}
|
||||
RedstoneGateBlock::update_target(
|
||||
&Self,
|
||||
&world,
|
||||
pos,
|
||||
props.to_state_id(block),
|
||||
block,
|
||||
),
|
||||
TickPriority::VeryHigh,
|
||||
);
|
||||
}
|
||||
});
|
||||
RedstoneGateBlock::update_target(
|
||||
self,
|
||||
args.world,
|
||||
*args.position,
|
||||
props.to_state_id(block),
|
||||
block,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
|
||||
|
||||
@ -42,7 +42,10 @@ impl SculkSensorBlock {
|
||||
if let Some(be) = world.get_block_entity(pos)
|
||||
&& let Some(sensor_be) = be.as_any().downcast_ref::<SculkSensorBlockEntity>()
|
||||
{
|
||||
*sensor_be.last_vibration_frequency.blocking_lock() = power as i32;
|
||||
*sensor_be
|
||||
.last_vibration_frequency
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner) = power as i32;
|
||||
}
|
||||
|
||||
props.sculk_sensor_phase = SculkSensorPhase::Active;
|
||||
@ -73,7 +76,10 @@ impl SculkSensorBlock {
|
||||
.as_any()
|
||||
.downcast_ref::<CalibratedSculkSensorBlockEntity>()
|
||||
{
|
||||
*cal_be.last_vibration_frequency.blocking_lock() = power as i32;
|
||||
*cal_be
|
||||
.last_vibration_frequency
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner) = power as i32;
|
||||
}
|
||||
|
||||
props.sculk_sensor_phase = SculkSensorPhase::Active;
|
||||
@ -136,13 +142,23 @@ impl BlockBehaviour for SculkSensorBlock {
|
||||
fn get_comparator_output(&self, args: GetComparatorOutputArgs<'_>) -> Option<u8> {
|
||||
let be = args.world.get_block_entity(args.position)?;
|
||||
if let Some(sensor_be) = be.as_any().downcast_ref::<SculkSensorBlockEntity>() {
|
||||
return Some(*sensor_be.last_vibration_frequency.blocking_lock() as u8);
|
||||
return Some(
|
||||
*sensor_be
|
||||
.last_vibration_frequency
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner) as u8,
|
||||
);
|
||||
}
|
||||
if let Some(cal_be) = be
|
||||
.as_any()
|
||||
.downcast_ref::<CalibratedSculkSensorBlockEntity>()
|
||||
{
|
||||
return Some(*cal_be.last_vibration_frequency.blocking_lock() as u8);
|
||||
return Some(
|
||||
*cal_be
|
||||
.last_vibration_frequency
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner) as u8,
|
||||
);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@ -68,7 +68,10 @@ impl SculkShriekerBlock {
|
||||
if let Some(entity) = world.get_block_entity(pos)
|
||||
&& let Some(shrieker) = entity.as_any().downcast_ref::<SculkShriekerBlockEntity>()
|
||||
{
|
||||
let mut level = shrieker.warning_level.lock().await;
|
||||
let mut level = shrieker
|
||||
.warning_level
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
*level = (*level + 1).min(4);
|
||||
if props.can_summon && *level >= 4 {
|
||||
// TODO: spawn Warden near pos
|
||||
|
||||
@ -2,8 +2,7 @@ use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_nbt::tag::NbtTag;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct BannerBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -33,18 +32,17 @@ impl BlockEntity for BannerBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if let Some(name) = self.custom_name.lock().await.as_ref() {
|
||||
nbt.put_string("CustomName", name.clone());
|
||||
}
|
||||
if let Some(pats) = self.patterns.lock().await.as_ref() {
|
||||
nbt.put_list("patterns", pats.clone());
|
||||
}
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(name) = self.custom_name.lock()
|
||||
&& let Some(name) = name.as_ref()
|
||||
{
|
||||
nbt.put_string("CustomName", name.clone());
|
||||
}
|
||||
if let Ok(pats) = self.patterns.lock()
|
||||
&& let Some(pats) = pats.as_ref()
|
||||
{
|
||||
nbt.put_list("patterns", pats.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
@ -73,8 +71,8 @@ impl BannerBlockEntity {
|
||||
pub const fn new(position: BlockPos) -> Self {
|
||||
Self {
|
||||
position,
|
||||
custom_name: Mutex::const_new(None),
|
||||
patterns: Mutex::const_new(None),
|
||||
custom_name: Mutex::new(None),
|
||||
patterns: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_util::random::xoroshiro128::Xoroshiro;
|
||||
use pumpkin_util::random::{RandomImpl, get_seed};
|
||||
use std::any::Any;
|
||||
use std::pin::Pin;
|
||||
use std::sync::RwLock;
|
||||
use std::{
|
||||
array::from_fn,
|
||||
@ -63,13 +62,8 @@ impl BlockEntity for BarrelBlockEntity {
|
||||
barrel
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
}
|
||||
|
||||
fn tick(&self, world: &Arc<World>) {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
use futures::Future;
|
||||
use pumpkin_data::data_component_impl::IDSetContent;
|
||||
use pumpkin_data::tag::Taggable;
|
||||
use std::any::Any;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
@ -262,36 +260,31 @@ impl BlockEntity for BeaconBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_int(
|
||||
"primary_effect",
|
||||
self.primary_effect.load(Ordering::Relaxed),
|
||||
);
|
||||
nbt.put_int(
|
||||
"secondary_effect",
|
||||
self.secondary_effect.load(Ordering::Relaxed),
|
||||
);
|
||||
nbt.put_int("Levels", self.levels.load(Ordering::Relaxed));
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
nbt.put_int(
|
||||
"primary_effect",
|
||||
self.primary_effect.load(Ordering::Relaxed),
|
||||
);
|
||||
nbt.put_int(
|
||||
"secondary_effect",
|
||||
self.secondary_effect.load(Ordering::Relaxed),
|
||||
);
|
||||
nbt.put_int("Levels", self.levels.load(Ordering::Relaxed));
|
||||
|
||||
if let Some(name) = &*self
|
||||
.custom_name
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
{
|
||||
nbt.put_string("CustomName", name.clone());
|
||||
}
|
||||
if let Some(lock) = &*self
|
||||
.lock_key
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
{
|
||||
nbt.put_string("Lock", lock.clone());
|
||||
}
|
||||
})
|
||||
if let Some(name) = &*self
|
||||
.custom_name
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
{
|
||||
nbt.put_string("CustomName", name.clone());
|
||||
}
|
||||
if let Some(lock) = &*self
|
||||
.lock_key
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
{
|
||||
nbt.put_string("Lock", lock.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&self, world: &Arc<World>) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use std::pin::Pin;
|
||||
|
||||
use pumpkin_data::{
|
||||
BlockState, BlockStateId,
|
||||
item::JavaToBedrockItemMapping,
|
||||
@ -30,12 +28,7 @@ impl BlockEntity for BedBlockEntity {
|
||||
Self { position }
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
_nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
fn write_nbt(&self, _nbt: &mut NbtCompound) {}
|
||||
|
||||
fn bedrock_block_actor_data(&self, state_id: BlockStateId) -> Option<NbtCompound> {
|
||||
let (block, _) = BlockState::from_id_with_block(state_id);
|
||||
|
||||
@ -2,8 +2,7 @@ use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_nbt::tag::NbtTag;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct BeehiveBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -39,22 +38,21 @@ impl BlockEntity for BeehiveBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if let Some(b) = self.bees.lock().await.as_ref() {
|
||||
nbt.put_list("Bees", b.clone());
|
||||
}
|
||||
if let Some(fp) = self.flower_pos.lock().await.as_ref() {
|
||||
let mut fp_nbt = NbtCompound::new();
|
||||
fp_nbt.put_int("X", fp.0.x);
|
||||
fp_nbt.put_int("Y", fp.0.y);
|
||||
fp_nbt.put_int("Z", fp.0.z);
|
||||
nbt.put_compound("FlowerPos", fp_nbt);
|
||||
}
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(b) = self.bees.lock()
|
||||
&& let Some(b) = b.as_ref()
|
||||
{
|
||||
nbt.put_list("Bees", b.clone());
|
||||
}
|
||||
if let Ok(fp) = self.flower_pos.lock()
|
||||
&& let Some(fp) = fp.as_ref()
|
||||
{
|
||||
let mut fp_nbt = NbtCompound::new();
|
||||
fp_nbt.put_int("X", fp.0.x);
|
||||
fp_nbt.put_int("Y", fp.0.y);
|
||||
fp_nbt.put_int("Z", fp.0.z);
|
||||
nbt.put_compound("FlowerPos", fp_nbt);
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
@ -87,8 +85,8 @@ impl BeehiveBlockEntity {
|
||||
pub const fn new(position: BlockPos) -> Self {
|
||||
Self {
|
||||
position,
|
||||
bees: Mutex::const_new(None),
|
||||
flower_pos: Mutex::const_new(None),
|
||||
bees: Mutex::new(None),
|
||||
flower_pos: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,6 @@ use pumpkin_data::sound::{Sound, SoundCategory};
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::any::Any;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct BellBlockEntity {
|
||||
@ -47,12 +46,7 @@ impl BellBlockEntity {
|
||||
}
|
||||
|
||||
impl BlockEntity for BellBlockEntity {
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
_nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {})
|
||||
}
|
||||
fn write_nbt(&self, _nbt: &mut NbtCompound) {}
|
||||
|
||||
fn from_nbt(_nbt: &NbtCompound, position: BlockPos) -> Self
|
||||
where
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
use std::any::Any;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::{
|
||||
Arc, Mutex as StdMutex, RwLock,
|
||||
atomic::AtomicI32,
|
||||
@ -401,18 +399,13 @@ impl crate::block::entities::BlockEntity for BrewingStandBlockEntity {
|
||||
entity
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
// Persist brew state
|
||||
nbt.put_int("BrewTime", self.brew_time.load(Ordering::Relaxed));
|
||||
nbt.put_int("Fuel", self.fuel.load(Ordering::Relaxed));
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
// Persist brew state
|
||||
nbt.put_int("BrewTime", self.brew_time.load(Ordering::Relaxed));
|
||||
nbt.put_int("Fuel", self.fuel.load(Ordering::Relaxed));
|
||||
|
||||
// Save inventory contents to NBT
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
})
|
||||
// Save inventory contents to NBT
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
}
|
||||
|
||||
fn get_inventory(self: Arc<Self>) -> Option<Arc<dyn Inventory>> {
|
||||
|
||||
@ -2,8 +2,7 @@ use super::BlockEntity;
|
||||
use pumpkin_data::item_stack::ItemStack;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct BrushableBlockBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -38,19 +37,20 @@ impl BlockEntity for BrushableBlockBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if let Some(it) = self.item.lock().await.as_ref() {
|
||||
let mut it_nbt = NbtCompound::new();
|
||||
it.write_item_stack(&mut it_nbt);
|
||||
nbt.put_compound("item", it_nbt);
|
||||
}
|
||||
nbt.put_int("hits", *self.hits.lock().await);
|
||||
nbt.put_byte("direction", *self.direction.lock().await as i8);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(item) = self.item.lock()
|
||||
&& let Some(it) = item.as_ref()
|
||||
{
|
||||
let mut it_nbt = NbtCompound::new();
|
||||
it.write_item_stack(&mut it_nbt);
|
||||
nbt.put_compound("item", it_nbt);
|
||||
}
|
||||
if let Ok(hits) = self.hits.lock() {
|
||||
nbt.put_int("hits", *hits);
|
||||
}
|
||||
if let Ok(direction) = self.direction.lock() {
|
||||
nbt.put_byte("direction", *direction as i8);
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
@ -78,9 +78,9 @@ impl BrushableBlockBlockEntity {
|
||||
pub const fn new(position: BlockPos) -> Self {
|
||||
Self {
|
||||
position,
|
||||
item: Mutex::const_new(None),
|
||||
hits: Mutex::const_new(0),
|
||||
direction: Mutex::const_new(0),
|
||||
item: Mutex::new(None),
|
||||
hits: Mutex::new(0),
|
||||
direction: Mutex::new(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct CalibratedSculkSensorBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -29,16 +28,10 @@ impl BlockEntity for CalibratedSculkSensorBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_int(
|
||||
"last_vibration_frequency",
|
||||
*self.last_vibration_frequency.lock().await,
|
||||
);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(freq) = self.last_vibration_frequency.lock() {
|
||||
nbt.put_int("last_vibration_frequency", *freq);
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -3,15 +3,13 @@ use pumpkin_data::item_stack::ItemStack;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_nbt::tag::NbtTag;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub struct CampfireBlockEntity {
|
||||
pub position: BlockPos,
|
||||
pub items: [Arc<Mutex<ItemStack>>; 4],
|
||||
pub cooking_times: [tokio::sync::Mutex<i32>; 4],
|
||||
pub cooking_total_times: [tokio::sync::Mutex<i32>; 4],
|
||||
pub cooking_times: [Mutex<i32>; 4],
|
||||
pub cooking_total_times: [Mutex<i32>; 4],
|
||||
}
|
||||
|
||||
impl BlockEntity for CampfireBlockEntity {
|
||||
@ -61,35 +59,35 @@ impl BlockEntity for CampfireBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
let mut list = Vec::new();
|
||||
for (i, item_mutex) in self.items.iter().enumerate() {
|
||||
let stack = item_mutex.lock().await;
|
||||
if !stack.is_empty() {
|
||||
let mut item_nbt = NbtCompound::new();
|
||||
item_nbt.put_byte("Slot", i as i8);
|
||||
stack.write_item_stack(&mut item_nbt);
|
||||
list.push(NbtTag::Compound(item_nbt));
|
||||
}
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
let mut list = Vec::new();
|
||||
for (i, item_mutex) in self.items.iter().enumerate() {
|
||||
if let Ok(stack) = item_mutex.lock()
|
||||
&& !stack.is_empty()
|
||||
{
|
||||
let mut item_nbt = NbtCompound::new();
|
||||
item_nbt.put_byte("Slot", i as i8);
|
||||
stack.write_item_stack(&mut item_nbt);
|
||||
list.push(NbtTag::Compound(item_nbt));
|
||||
}
|
||||
nbt.put_list("Items", list);
|
||||
}
|
||||
nbt.put_list("Items", list);
|
||||
|
||||
let mut times = Vec::new();
|
||||
for m in &self.cooking_times {
|
||||
times.push(*m.lock().await);
|
||||
let mut times = Vec::new();
|
||||
for m in &self.cooking_times {
|
||||
if let Ok(t) = m.lock() {
|
||||
times.push(*t);
|
||||
}
|
||||
nbt.put("CookingTimes", NbtTag::IntArray(times));
|
||||
}
|
||||
nbt.put("CookingTimes", NbtTag::IntArray(times));
|
||||
|
||||
let mut total_times = Vec::new();
|
||||
for m in &self.cooking_total_times {
|
||||
total_times.push(*m.lock().await);
|
||||
let mut total_times = Vec::new();
|
||||
for m in &self.cooking_total_times {
|
||||
if let Ok(t) = m.lock() {
|
||||
total_times.push(*t);
|
||||
}
|
||||
nbt.put("CookingTotalTimes", NbtTag::IntArray(total_times));
|
||||
})
|
||||
}
|
||||
nbt.put("CookingTotalTimes", NbtTag::IntArray(total_times));
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
|
||||
@ -52,33 +52,27 @@ macro_rules! impl_block_entity_for_chest {
|
||||
chest
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut pumpkin_nbt::compound::NbtCompound,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send + 'a>> {
|
||||
fn write_nbt(&self, nbt: &mut pumpkin_nbt::compound::NbtCompound) {
|
||||
use pumpkin_world::inventory::Inventory;
|
||||
|
||||
Box::pin(async move {
|
||||
// Clone the loot table key without holding the lock across an await.
|
||||
let loot_table_key = {
|
||||
let guard = self
|
||||
.loot_table
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
guard.clone()
|
||||
};
|
||||
let loot_table_key = {
|
||||
let guard = self
|
||||
.loot_table
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
guard.clone()
|
||||
};
|
||||
|
||||
if let Some(key) = loot_table_key {
|
||||
// Persist deferred loot: write the key and seed; skip items.
|
||||
nbt.put_string("LootTable", key);
|
||||
if self.loot_table_seed != 0 {
|
||||
nbt.put_long("LootTableSeed", self.loot_table_seed);
|
||||
}
|
||||
} else {
|
||||
// Loot has already been generated, so persist the actual items.
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
if let Some(key) = loot_table_key {
|
||||
// Persist deferred loot: write the key and seed; skip items.
|
||||
nbt.put_string("LootTable", key);
|
||||
if self.loot_table_seed != 0 {
|
||||
nbt.put_long("LootTableSeed", self.loot_table_seed);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// Loot has already been generated, so persist the actual items.
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&self, world: &Arc<$crate::world::World>) {
|
||||
|
||||
@ -4,8 +4,6 @@ use pumpkin_data::item_stack::ItemStack;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::any::Any;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::RwLock;
|
||||
use std::{
|
||||
array::from_fn,
|
||||
@ -66,21 +64,16 @@ impl BlockEntity for ChiseledBookshelfBlockEntity {
|
||||
bookshelf
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
let items = self
|
||||
.items
|
||||
.read()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
sync_write_items_to_nbt(items.as_slice(), nbt);
|
||||
nbt.put_int(
|
||||
LAST_INTERACTED_SLOT,
|
||||
i32::from(self.last_interacted_slot.load(Ordering::Relaxed)),
|
||||
);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
let items = self
|
||||
.items
|
||||
.read()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
sync_write_items_to_nbt(items.as_slice(), nbt);
|
||||
nbt.put_int(
|
||||
LAST_INTERACTED_SLOT,
|
||||
i32::from(self.last_interacted_slot.load(Ordering::Relaxed)),
|
||||
);
|
||||
}
|
||||
|
||||
fn get_inventory(self: Arc<Self>) -> Option<Arc<dyn Inventory>> {
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
use std::{
|
||||
pin::Pin,
|
||||
sync::{
|
||||
Mutex as StdMutex,
|
||||
atomic::{AtomicBool, AtomicU32, Ordering},
|
||||
},
|
||||
use std::sync::{
|
||||
Mutex as StdMutex,
|
||||
atomic::{AtomicBool, AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
@ -102,13 +99,8 @@ impl BlockEntity for CommandBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn std::future::Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async {
|
||||
self.write_sync_nbt(nbt);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
self.write_sync_nbt(nbt);
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
use std::{
|
||||
pin::Pin,
|
||||
sync::atomic::{AtomicU8, Ordering},
|
||||
};
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
@ -46,16 +43,11 @@ impl BlockEntity for ComparatorBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_int(
|
||||
OUTPUT_SIGNAL,
|
||||
self.output_signal.load(Ordering::Relaxed) as i32,
|
||||
);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
nbt.put_int(
|
||||
OUTPUT_SIGNAL,
|
||||
self.output_signal.load(Ordering::Relaxed) as i32,
|
||||
);
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -2,8 +2,7 @@ use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_nbt::tag::NbtTag;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct ConduitBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -33,16 +32,15 @@ impl BlockEntity for ConduitBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_bool("Active", *self.active.lock().await);
|
||||
if let Some(tgt) = self.target.lock().await.as_ref() {
|
||||
nbt.put("Target", tgt.clone());
|
||||
}
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(active) = self.active.lock() {
|
||||
nbt.put_bool("Active", *active);
|
||||
}
|
||||
if let Ok(target) = self.target.lock()
|
||||
&& let Some(tgt) = target.as_ref()
|
||||
{
|
||||
nbt.put("Target", tgt.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use std::pin::Pin;
|
||||
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
|
||||
@ -25,12 +23,7 @@ impl BlockEntity for CopperGolemStatueBlockEntity {
|
||||
Self { position }
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
_nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
fn write_nbt(&self, _nbt: &mut NbtCompound) {}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
|
||||
@ -5,7 +5,6 @@ use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::inventory::{Clearable, Inventory, sync_write_items_to_nbt};
|
||||
use std::any::Any;
|
||||
use std::array::from_fn;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
|
||||
@ -19,22 +18,17 @@ pub struct CrafterBlockEntity {
|
||||
}
|
||||
|
||||
impl BlockEntity for CrafterBlockEntity {
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
let items = self
|
||||
.items
|
||||
.read()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
sync_write_items_to_nbt(items.as_slice(), nbt);
|
||||
nbt.put_int(
|
||||
"crafting_ticks_remaining",
|
||||
self.crafting_ticks_remaining.load(Ordering::Relaxed),
|
||||
);
|
||||
nbt.put_bool("triggered", self.triggered.load(Ordering::Relaxed));
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
let items = self
|
||||
.items
|
||||
.read()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
sync_write_items_to_nbt(items.as_slice(), nbt);
|
||||
nbt.put_int(
|
||||
"crafting_ticks_remaining",
|
||||
self.crafting_ticks_remaining.load(Ordering::Relaxed),
|
||||
);
|
||||
nbt.put_bool("triggered", self.triggered.load(Ordering::Relaxed));
|
||||
}
|
||||
|
||||
fn from_nbt(nbt: &pumpkin_nbt::compound::NbtCompound, position: BlockPos) -> Self
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
@ -38,15 +37,10 @@ impl BlockEntity for CreakingHeartBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if let Some(uuid) = self.creaking_uuid.load() {
|
||||
nbt.put_string("creaking_uuid", uuid.to_string());
|
||||
}
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Some(uuid) = self.creaking_uuid.load() {
|
||||
nbt.put_string("creaking_uuid", uuid.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use pumpkin_data::block_properties::BlockProperties;
|
||||
@ -31,12 +30,7 @@ impl BlockEntity for DaylightDetectorBlockEntity {
|
||||
Self { position }
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
_nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
fn write_nbt(&self, _nbt: &mut NbtCompound) {}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
|
||||
@ -3,8 +3,7 @@ use pumpkin_data::item_stack::ItemStack;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_nbt::tag::NbtTag;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct DecoratedPotBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -36,20 +35,19 @@ impl BlockEntity for DecoratedPotBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if let Some(sh) = self.sherds.lock().await.as_ref() {
|
||||
nbt.put_list("sherds", sh.clone());
|
||||
}
|
||||
if let Some(it) = self.item.lock().await.as_ref() {
|
||||
let mut it_nbt = NbtCompound::new();
|
||||
it.write_item_stack(&mut it_nbt);
|
||||
nbt.put_compound("item", it_nbt);
|
||||
}
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(sherds) = self.sherds.lock()
|
||||
&& let Some(sh) = sherds.as_ref()
|
||||
{
|
||||
nbt.put_list("sherds", sh.clone());
|
||||
}
|
||||
if let Ok(item) = self.item.lock()
|
||||
&& let Some(it) = item.as_ref()
|
||||
{
|
||||
let mut it_nbt = NbtCompound::new();
|
||||
it.write_item_stack(&mut it_nbt);
|
||||
nbt.put_compound("item", it_nbt);
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
@ -81,21 +79,30 @@ impl DecoratedPotBlockEntity {
|
||||
pub const fn new(position: BlockPos) -> Self {
|
||||
Self {
|
||||
position,
|
||||
sherds: Mutex::const_new(None),
|
||||
item: Mutex::const_new(None),
|
||||
sherds: Mutex::new(None),
|
||||
item: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_item(&self) -> Option<ItemStack> {
|
||||
self.item.blocking_lock().clone()
|
||||
self.item
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub fn take_item(&self) -> Option<ItemStack> {
|
||||
self.item.blocking_lock().take()
|
||||
self.item
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.take()
|
||||
}
|
||||
|
||||
pub fn try_insert_item(&self, stack: &mut ItemStack, count: u8) -> bool {
|
||||
let mut item_guard = self.item.blocking_lock();
|
||||
let mut item_guard = self
|
||||
.item
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if let Some(existing) = item_guard.as_mut() {
|
||||
if existing.item.id == stack.item.id {
|
||||
let add = count.min(64 - existing.item_count);
|
||||
@ -117,13 +124,17 @@ impl DecoratedPotBlockEntity {
|
||||
}
|
||||
|
||||
pub fn get_comparator_output(&self) -> u8 {
|
||||
self.item.blocking_lock().as_ref().map_or(0, |item| {
|
||||
if item.item_count == 0 {
|
||||
0
|
||||
} else {
|
||||
let max_count = 64f32;
|
||||
1 + ((item.item_count as f32 / max_count) * 14.0).floor() as u8
|
||||
}
|
||||
})
|
||||
self.item
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.as_ref()
|
||||
.map_or(0, |item| {
|
||||
if item.item_count == 0 {
|
||||
0
|
||||
} else {
|
||||
let max_count = 64f32;
|
||||
1 + ((item.item_count as f32 / max_count) * 14.0).floor() as u8
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,6 @@ use pumpkin_world::inventory::{Clearable, Inventory, sync_write_items_to_nbt};
|
||||
use rand::{RngExt, rng};
|
||||
use std::any::Any;
|
||||
use std::array::from_fn;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@ -18,13 +17,8 @@ pub struct DispenserBlockEntity {
|
||||
}
|
||||
|
||||
impl BlockEntity for DispenserBlockEntity {
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
}
|
||||
|
||||
fn from_nbt(nbt: &pumpkin_nbt::compound::NbtCompound, position: BlockPos) -> Self
|
||||
|
||||
@ -6,7 +6,6 @@ use pumpkin_world::inventory::{Clearable, Inventory, sync_write_items_to_nbt};
|
||||
use rand::{RngExt, rng};
|
||||
use std::any::Any;
|
||||
use std::array::from_fn;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@ -18,13 +17,8 @@ pub struct DropperBlockEntity {
|
||||
}
|
||||
|
||||
impl BlockEntity for DropperBlockEntity {
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
}
|
||||
|
||||
fn from_nbt(nbt: &pumpkin_nbt::compound::NbtCompound, position: BlockPos) -> Self
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct EnchantingTableBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -29,15 +28,12 @@ impl BlockEntity for EnchantingTableBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if let Some(name) = self.custom_name.lock().await.as_ref() {
|
||||
nbt.put_string("CustomName", name.clone());
|
||||
}
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(name) = self.custom_name.lock()
|
||||
&& let Some(name) = name.as_ref()
|
||||
{
|
||||
nbt.put_string("CustomName", name.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
@ -61,7 +57,7 @@ impl EnchantingTableBlockEntity {
|
||||
pub const fn new(position: BlockPos) -> Self {
|
||||
Self {
|
||||
position,
|
||||
custom_name: Mutex::const_new(None),
|
||||
custom_name: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct EndGatewayBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -41,21 +40,22 @@ impl BlockEntity for EndGatewayBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_long("Age", *self.age.lock().await);
|
||||
nbt.put_bool("ExactTeleport", *self.exact_teleport.lock().await);
|
||||
if let Some(exit) = self.exit_portal.lock().await.as_ref() {
|
||||
let mut exit_nbt = NbtCompound::new();
|
||||
exit_nbt.put_int("X", exit.0.x);
|
||||
exit_nbt.put_int("Y", exit.0.y);
|
||||
exit_nbt.put_int("Z", exit.0.z);
|
||||
nbt.put_compound("ExitPortal", exit_nbt);
|
||||
}
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(age) = self.age.lock() {
|
||||
nbt.put_long("Age", *age);
|
||||
}
|
||||
if let Ok(exact_teleport) = self.exact_teleport.lock() {
|
||||
nbt.put_bool("ExactTeleport", *exact_teleport);
|
||||
}
|
||||
if let Ok(exit_portal) = self.exit_portal.lock()
|
||||
&& let Some(exit) = exit_portal.as_ref()
|
||||
{
|
||||
let mut exit_nbt = NbtCompound::new();
|
||||
exit_nbt.put_int("X", exit.0.x);
|
||||
exit_nbt.put_int("Y", exit.0.y);
|
||||
exit_nbt.put_int("Z", exit.0.z);
|
||||
nbt.put_compound("ExitPortal", exit_nbt);
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use std::pin::Pin;
|
||||
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
|
||||
@ -43,12 +41,7 @@ impl BlockEntity for EndPortalBlockEntity {
|
||||
Self { position }
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
_nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
fn write_nbt(&self, _nbt: &mut NbtCompound) {}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
|
||||
@ -4,7 +4,6 @@ use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_util::random::xoroshiro128::Xoroshiro;
|
||||
use pumpkin_util::random::{RandomImpl, get_seed};
|
||||
use std::any::Any;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::block::viewer::{ViewerCountListener, ViewerCountTracker, ViewerCountTrackerExt};
|
||||
@ -38,12 +37,7 @@ impl BlockEntity for EnderChestBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
_nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
fn write_nbt(&self, _nbt: &mut NbtCompound) {}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
Some(NbtCompound::new())
|
||||
|
||||
@ -552,39 +552,34 @@ macro_rules! impl_block_entity_for_cooking {
|
||||
furnace
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut pumpkin_nbt::compound::NbtCompound,
|
||||
) -> std::pin::Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_short("cooking_total_time", self.get_cooking_total_time() as i16);
|
||||
nbt.put_short("cooking_time_spent", self.get_cooking_time_spent() as i16);
|
||||
nbt.put_short("lit_total_time", self.get_lit_total_time() as i16);
|
||||
nbt.put_short("lit_time_remaining", self.get_lit_time_remaining() as i16);
|
||||
fn write_nbt(&self, nbt: &mut pumpkin_nbt::compound::NbtCompound) {
|
||||
nbt.put_short("cooking_total_time", self.get_cooking_total_time() as i16);
|
||||
nbt.put_short("cooking_time_spent", self.get_cooking_time_spent() as i16);
|
||||
nbt.put_short("lit_total_time", self.get_lit_total_time() as i16);
|
||||
nbt.put_short("lit_time_remaining", self.get_lit_time_remaining() as i16);
|
||||
|
||||
// Save RecipesUsed in vanilla format (map of recipe ID -> craft count)
|
||||
{
|
||||
let recipes = self
|
||||
.recipes_used
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if !recipes.is_empty() {
|
||||
let mut recipes_compound = pumpkin_nbt::compound::NbtCompound::new();
|
||||
for (recipe_id, count) in recipes.iter() {
|
||||
recipes_compound.put(
|
||||
recipe_id.as_str(),
|
||||
pumpkin_nbt::tag::NbtTag::Int(*count as i32),
|
||||
);
|
||||
}
|
||||
nbt.put(
|
||||
"RecipesUsed",
|
||||
pumpkin_nbt::tag::NbtTag::Compound(recipes_compound),
|
||||
// Save RecipesUsed in vanilla format (map of recipe ID -> craft count)
|
||||
{
|
||||
let recipes = self
|
||||
.recipes_used
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if !recipes.is_empty() {
|
||||
let mut recipes_compound = pumpkin_nbt::compound::NbtCompound::new();
|
||||
for (recipe_id, count) in recipes.iter() {
|
||||
recipes_compound.put(
|
||||
recipe_id.as_str(),
|
||||
pumpkin_nbt::tag::NbtTag::Int(*count as i32),
|
||||
);
|
||||
}
|
||||
nbt.put(
|
||||
"RecipesUsed",
|
||||
pumpkin_nbt::tag::NbtTag::Compound(recipes_compound),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
})
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
}
|
||||
|
||||
fn get_inventory(
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
use std::{
|
||||
pin::Pin,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
},
|
||||
use std::sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use super::BlockEntity;
|
||||
@ -53,15 +50,10 @@ impl BlockEntity for HangingSignBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put("front_text", self.front_text.clone());
|
||||
nbt.put("back_text", self.back_text.clone());
|
||||
nbt.put_bool("is_waxed", self.is_waxed.load(Ordering::Relaxed));
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
nbt.put("front_text", self.front_text.clone());
|
||||
nbt.put("back_text", self.back_text.clone());
|
||||
nbt.put_bool("is_waxed", self.is_waxed.load(Ordering::Relaxed));
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -13,7 +13,6 @@ use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_world::inventory::{Clearable, Inventory, sync_write_items_to_nbt};
|
||||
use std::any::Any;
|
||||
use std::array::from_fn;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::atomic::Ordering;
|
||||
@ -41,17 +40,12 @@ pub fn to_offset(facing: &FacingHopper) -> Vector3<i32> {
|
||||
}
|
||||
|
||||
impl BlockEntity for HopperBlockEntity {
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put(
|
||||
"TransferCooldown",
|
||||
NbtTag::Int(self.cooldown_time.load(Ordering::Relaxed)),
|
||||
);
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
nbt.put(
|
||||
"TransferCooldown",
|
||||
NbtTag::Int(self.cooldown_time.load(Ordering::Relaxed)),
|
||||
);
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
}
|
||||
|
||||
fn from_nbt(nbt: &pumpkin_nbt::compound::NbtCompound, position: BlockPos) -> Self
|
||||
@ -89,13 +83,9 @@ impl BlockEntity for HopperBlockEntity {
|
||||
);
|
||||
if state.enabled
|
||||
&& let Some(entity) = world.get_block_entity(&self.position)
|
||||
&& let Some(hopper) = entity.as_any().downcast_ref::<Self>()
|
||||
{
|
||||
let world = world.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Some(hopper) = entity.as_any().downcast_ref::<Self>() {
|
||||
hopper.try_move_items(&state, &world).await;
|
||||
}
|
||||
});
|
||||
hopper.try_move_items(state, world);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,15 +147,15 @@ impl HopperBlockEntity {
|
||||
ticked_game_time: AtomicI64::new(0),
|
||||
}
|
||||
}
|
||||
async fn try_move_items(&self, state: &HopperLikeProperties, world: &Arc<World>) {
|
||||
fn try_move_items(&self, state: HopperLikeProperties, world: &Arc<World>) {
|
||||
if self.cooldown_time.load(Ordering::Relaxed) <= 0 && state.enabled {
|
||||
let mut success = if self.is_empty() {
|
||||
false
|
||||
} else {
|
||||
self.eject_items(world).await
|
||||
self.eject_items(world)
|
||||
};
|
||||
if !self.inventory_full() {
|
||||
success |= self.suck_in_items(world).await;
|
||||
success |= self.suck_in_items(world);
|
||||
}
|
||||
if success {
|
||||
self.cooldown_time.store(8, Ordering::Relaxed);
|
||||
@ -187,7 +177,7 @@ impl HopperBlockEntity {
|
||||
true
|
||||
}
|
||||
|
||||
async fn suck_in_items(&self, world: &Arc<World>) -> bool {
|
||||
fn suck_in_items(&self, world: &Arc<World>) -> bool {
|
||||
// TODO getEntityContainer
|
||||
let pos_up = &self.position.up();
|
||||
let mut search_event = crate::plugin::api::events::inventory::hopper_inventory_search::HopperInventorySearchEvent::new(
|
||||
@ -195,7 +185,9 @@ impl HopperBlockEntity {
|
||||
*pos_up,
|
||||
);
|
||||
if let Some(server) = world.server.upgrade() {
|
||||
server.plugin_manager.fire(&server, &mut search_event).await;
|
||||
server
|
||||
.plugin_manager
|
||||
.fire_blocking(&server, &mut search_event);
|
||||
}
|
||||
if search_event.cancelled {
|
||||
return false;
|
||||
@ -256,7 +248,9 @@ impl HopperBlockEntity {
|
||||
registry_key,
|
||||
);
|
||||
if let Some(server) = world.server.upgrade() {
|
||||
server.plugin_manager.fire(&server, &mut pickup_event).await;
|
||||
server
|
||||
.plugin_manager
|
||||
.fire_blocking(&server, &mut pickup_event);
|
||||
}
|
||||
if pickup_event.cancelled {
|
||||
continue;
|
||||
@ -292,7 +286,7 @@ impl HopperBlockEntity {
|
||||
false
|
||||
}
|
||||
|
||||
async fn eject_items(&self, world: &Arc<World>) -> bool {
|
||||
fn eject_items(&self, world: &Arc<World>) -> bool {
|
||||
// TODO getEntityContainer
|
||||
|
||||
if let Some(entity) = world.get_block_entity(&self.position.offset(to_offset(&self.facing)))
|
||||
@ -325,7 +319,9 @@ impl HopperBlockEntity {
|
||||
1,
|
||||
);
|
||||
if let Some(server) = world.server.upgrade() {
|
||||
server.plugin_manager.fire(&server, &mut move_event).await;
|
||||
server
|
||||
.plugin_manager
|
||||
.fire_blocking(&server, &mut move_event);
|
||||
}
|
||||
if move_event.cancelled {
|
||||
continue;
|
||||
|
||||
@ -1,13 +1,9 @@
|
||||
use rand::Rng;
|
||||
use std::{
|
||||
pin::Pin,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, AtomicI32, Ordering},
|
||||
},
|
||||
use std::sync::{
|
||||
Arc, Mutex,
|
||||
atomic::{AtomicBool, AtomicI32, Ordering},
|
||||
};
|
||||
|
||||
use futures::Future;
|
||||
use pumpkin_data::block_properties::{BlockProperties, JigsawLikeProperties, Orientation};
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::{
|
||||
@ -22,8 +18,6 @@ use pumpkin_world::generation::structure::structures::{
|
||||
},
|
||||
};
|
||||
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::block::blocks::jigsaw::JigsawBlock;
|
||||
use crate::world::World;
|
||||
|
||||
@ -81,8 +75,16 @@ impl JigsawBlockEntity {
|
||||
}
|
||||
|
||||
pub async fn generate(&self, world: &Arc<World>, levels: i32, keep_jigsaws: bool) {
|
||||
let pool = self.pool.lock().await.clone();
|
||||
let target = self.target.lock().await.clone();
|
||||
let pool = self
|
||||
.pool
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.clone();
|
||||
let target = self
|
||||
.target
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.clone();
|
||||
|
||||
let block_state = world.get_block_state(&self.position);
|
||||
let props =
|
||||
@ -206,26 +208,30 @@ impl BlockEntity for JigsawBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_string(Self::NAME, self.name.lock().await.clone());
|
||||
nbt.put_string(Self::TARGET, self.target.lock().await.clone());
|
||||
nbt.put_string(Self::POOL, self.pool.lock().await.clone());
|
||||
nbt.put_string(Self::FINAL_STATE, self.final_state.lock().await.clone());
|
||||
let joint = *self.joint.lock().await;
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(name) = self.name.lock() {
|
||||
nbt.put_string(Self::NAME, name.clone());
|
||||
}
|
||||
if let Ok(target) = self.target.lock() {
|
||||
nbt.put_string(Self::TARGET, target.clone());
|
||||
}
|
||||
if let Ok(pool) = self.pool.lock() {
|
||||
nbt.put_string(Self::POOL, pool.clone());
|
||||
}
|
||||
if let Ok(final_state) = self.final_state.lock() {
|
||||
nbt.put_string(Self::FINAL_STATE, final_state.clone());
|
||||
}
|
||||
if let Ok(joint) = self.joint.lock() {
|
||||
nbt.put_string(Self::JOINT, joint.as_str().to_string());
|
||||
nbt.put_int(
|
||||
Self::PLACEMENT_PRIORITY,
|
||||
self.placement_priority.load(Ordering::SeqCst),
|
||||
);
|
||||
nbt.put_int(
|
||||
Self::SELECTION_PRIORITY,
|
||||
self.selection_priority.load(Ordering::SeqCst),
|
||||
);
|
||||
})
|
||||
}
|
||||
nbt.put_int(
|
||||
Self::PLACEMENT_PRIORITY,
|
||||
self.placement_priority.load(Ordering::SeqCst),
|
||||
);
|
||||
nbt.put_int(
|
||||
Self::SELECTION_PRIORITY,
|
||||
self.selection_priority.load(Ordering::SeqCst),
|
||||
);
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
use std::any::Any;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
@ -58,26 +56,21 @@ impl BlockEntity for JukeboxBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
let record = self
|
||||
.record_stack
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if !record.is_empty() {
|
||||
let mut record_nbt = NbtCompound::new();
|
||||
record.write_item_stack(&mut record_nbt);
|
||||
nbt.put(RECORD_ITEM_NBT_KEY, record_nbt);
|
||||
}
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
let record = self
|
||||
.record_stack
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if !record.is_empty() {
|
||||
let mut record_nbt = NbtCompound::new();
|
||||
record.write_item_stack(&mut record_nbt);
|
||||
nbt.put(RECORD_ITEM_NBT_KEY, record_nbt);
|
||||
}
|
||||
|
||||
let ticks = self.ticks_since_song_started.load(Ordering::Relaxed);
|
||||
if ticks > 0 {
|
||||
nbt.put_long(TICKS_SINCE_SONG_STARTED_NBT_KEY, ticks as i64);
|
||||
}
|
||||
})
|
||||
let ticks = self.ticks_since_song_started.load(Ordering::Relaxed);
|
||||
if ticks > 0 {
|
||||
nbt.put_long(TICKS_SINCE_SONG_STARTED_NBT_KEY, ticks as i64);
|
||||
}
|
||||
}
|
||||
|
||||
fn tick(&self, _world: &Arc<World>) {
|
||||
|
||||
@ -5,8 +5,6 @@ use pumpkin_nbt::tag::NbtTag;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::{
|
||||
any::Any,
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
sync::{
|
||||
Arc, Mutex,
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
@ -56,22 +54,17 @@ impl BlockEntity for LecternBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
let book = self
|
||||
.book
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if !book.is_empty() {
|
||||
let mut book_nbt = NbtCompound::default();
|
||||
book.write_item_stack(&mut book_nbt);
|
||||
nbt.put_compound("Book", book_nbt);
|
||||
}
|
||||
nbt.put_int("Page", self.page.load(Ordering::Relaxed) as i32);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
let book = self
|
||||
.book
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if !book.is_empty() {
|
||||
let mut book_nbt = NbtCompound::default();
|
||||
book.write_item_stack(&mut book_nbt);
|
||||
nbt.put_compound("Book", book_nbt);
|
||||
}
|
||||
nbt.put_int("Page", self.page.load(Ordering::Relaxed) as i32);
|
||||
}
|
||||
|
||||
fn get_inventory(self: Arc<Self>) -> Option<Arc<dyn Inventory>> {
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
use std::any::Any;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
|
||||
|
||||
@ -162,19 +160,14 @@ impl BlockEntity for MapBlockEntity {
|
||||
entity
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_int("MapId", self.get_map_id());
|
||||
let colors = self
|
||||
.colors
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let colors_i8: Vec<i8> = colors.iter().map(|&b| b as i8).collect();
|
||||
nbt.put("Colors", NbtTag::ByteArray(colors_i8.into_boxed_slice()));
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
nbt.put_int("MapId", self.get_map_id());
|
||||
let colors = self
|
||||
.colors
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let colors_i8: Vec<i8> = colors.iter().map(|&b| b as i8).collect();
|
||||
nbt.put("Colors", NbtTag::ByteArray(colors_i8.into_boxed_slice()));
|
||||
}
|
||||
|
||||
fn is_dirty(&self) -> bool {
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
use std::{
|
||||
pin::Pin,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicI32, Ordering},
|
||||
},
|
||||
use std::sync::{
|
||||
Arc,
|
||||
atomic::{AtomicI32, Ordering},
|
||||
};
|
||||
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
@ -54,13 +51,7 @@ impl MobSpawnerBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_nbt<'a>(&'a self, nbt: &'a mut NbtCompound) {
|
||||
// TODO: this is ugly af
|
||||
nbt.put_string("id", self.resource_location().to_string());
|
||||
let position = self.get_position();
|
||||
nbt.put_int("x", position.0.x);
|
||||
nbt.put_int("y", position.0.y);
|
||||
nbt.put_int("z", position.0.z);
|
||||
pub fn write_spawner_nbt(&self, nbt: &mut NbtCompound) {
|
||||
nbt.put_short("Delay", self.delay.load(Ordering::Relaxed) as i16);
|
||||
nbt.put_short("MinSpawnDelay", self.min_delay as i16);
|
||||
nbt.put_short("MaxSpawnDelay", self.max_delay as i16);
|
||||
@ -264,13 +255,8 @@ impl BlockEntity for MobSpawnerBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
self.write_nbt(nbt);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
self.write_spawner_nbt(nbt);
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -69,10 +69,7 @@ pub use pumpkin_world::block::entities::PropertyDelegate;
|
||||
|
||||
//TODO: We need a mark_dirty for chests
|
||||
pub trait BlockEntity: Any + Send + Sync {
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound);
|
||||
fn from_nbt(nbt: &NbtCompound, position: BlockPos) -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
@ -95,18 +92,13 @@ pub trait BlockEntity: Any + Send + Sync {
|
||||
false
|
||||
}
|
||||
|
||||
fn write_internal<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_string("id", self.resource_location().to_string());
|
||||
let position = self.get_position();
|
||||
nbt.put_int("x", position.0.x);
|
||||
nbt.put_int("y", position.0.y);
|
||||
nbt.put_int("z", position.0.z);
|
||||
self.write_nbt(nbt).await;
|
||||
})
|
||||
fn write_internal(&self, nbt: &mut NbtCompound) {
|
||||
nbt.put_string("id", self.resource_location().to_string());
|
||||
let position = self.get_position();
|
||||
nbt.put_int("x", position.0.x);
|
||||
nbt.put_int("y", position.0.y);
|
||||
nbt.put_int("z", position.0.z);
|
||||
self.write_nbt(nbt);
|
||||
}
|
||||
fn get_id(&self) -> u32 {
|
||||
let name = self
|
||||
@ -462,7 +454,7 @@ mod test {
|
||||
furnace.set_stack(0, ItemStack::new(5, &Item::DIAMOND));
|
||||
|
||||
let mut nbt = NbtCompound::new();
|
||||
furnace.write_internal(&mut nbt).await;
|
||||
furnace.write_internal(&mut nbt);
|
||||
|
||||
let inventory = block_entity_from_nbt(&nbt).and_then(BlockEntity::get_inventory);
|
||||
assert!(
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::{pin::Pin, sync::Arc};
|
||||
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use pumpkin_data::{Block, BlockDirection, BlockState};
|
||||
@ -274,17 +274,12 @@ impl BlockEntity for PistonBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
// TODO: pushed_block_state
|
||||
nbt.put_byte(FACING, self.facing.to_index() as i8);
|
||||
nbt.put_float(LAST_PROGRESS, self.last_progress.load());
|
||||
nbt.put_bool(EXTENDING, self.extending);
|
||||
nbt.put_bool(SOURCE, self.source);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
// TODO: pushed_block_state
|
||||
nbt.put_byte(FACING, self.facing.to_index() as i8);
|
||||
nbt.put_float(LAST_PROGRESS, self.last_progress.load());
|
||||
nbt.put_bool(EXTENDING, self.extending);
|
||||
nbt.put_bool(SOURCE, self.source);
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use std::pin::Pin;
|
||||
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
|
||||
@ -25,12 +23,7 @@ impl BlockEntity for PotentSulfurBlockEntity {
|
||||
Self { position }
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
_nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
fn write_nbt(&self, _nbt: &mut NbtCompound) {}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct SculkCatalystBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -29,13 +28,10 @@ impl BlockEntity for SculkCatalystBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_int("decay_delay", *self.decay_delay.lock().await);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(decay_delay) = self.decay_delay.lock() {
|
||||
nbt.put_int("decay_delay", *decay_delay);
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct SculkSensorBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -29,16 +28,10 @@ impl BlockEntity for SculkSensorBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_int(
|
||||
"last_vibration_frequency",
|
||||
*self.last_vibration_frequency.lock().await,
|
||||
);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(last_vibration_frequency) = self.last_vibration_frequency.lock() {
|
||||
nbt.put_int("last_vibration_frequency", *last_vibration_frequency);
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct SculkShriekerBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -29,13 +28,10 @@ impl BlockEntity for SculkShriekerBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_int("warning_level", *self.warning_level.lock().await);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(warning_level) = self.warning_level.lock() {
|
||||
nbt.put_int("warning_level", *warning_level);
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -5,7 +5,6 @@ use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::inventory::{Clearable, Inventory, sync_write_items_to_nbt};
|
||||
use std::any::Any;
|
||||
use std::array::from_fn;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@ -17,13 +16,8 @@ pub struct ShelfBlockEntity {
|
||||
}
|
||||
|
||||
impl BlockEntity for ShelfBlockEntity {
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
}
|
||||
|
||||
fn from_nbt(nbt: &pumpkin_nbt::compound::NbtCompound, position: BlockPos) -> Self
|
||||
|
||||
@ -54,13 +54,8 @@ impl BlockEntity for ShulkerBoxBlockEntity {
|
||||
shulker_box
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
self.write_inventory_nbt(nbt, true);
|
||||
}
|
||||
|
||||
fn tick(&self, world: &Arc<World>) {
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
use std::{
|
||||
pin::Pin,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, AtomicI8, Ordering},
|
||||
},
|
||||
use std::sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, AtomicI8, Ordering},
|
||||
};
|
||||
|
||||
use super::BlockEntity;
|
||||
@ -155,15 +152,10 @@ impl BlockEntity for SignBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put("front_text", self.front_text.clone());
|
||||
nbt.put("back_text", self.back_text.clone());
|
||||
nbt.put_bool("is_waxed", self.is_waxed.load(Ordering::Relaxed));
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
nbt.put("front_text", self.front_text.clone());
|
||||
nbt.put("back_text", self.back_text.clone());
|
||||
nbt.put_bool("is_waxed", self.is_waxed.load(Ordering::Relaxed));
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct SkullBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -32,18 +31,17 @@ impl BlockEntity for SkullBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if let Some(sound) = self.note_block_sound.lock().await.as_ref() {
|
||||
nbt.put_string("note_block_sound", sound.clone());
|
||||
}
|
||||
if let Some(prof) = self.profile.lock().await.as_ref() {
|
||||
nbt.put_compound("profile", prof.clone());
|
||||
}
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(sound) = self.note_block_sound.lock()
|
||||
&& let Some(sound) = sound.as_ref()
|
||||
{
|
||||
nbt.put_string("note_block_sound", sound.clone());
|
||||
}
|
||||
if let Ok(prof) = self.profile.lock()
|
||||
&& let Some(prof) = prof.as_ref()
|
||||
{
|
||||
nbt.put_compound("profile", prof.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
@ -72,8 +70,8 @@ impl SkullBlockEntity {
|
||||
pub const fn new(position: BlockPos) -> Self {
|
||||
Self {
|
||||
position,
|
||||
note_block_sound: Mutex::const_new(None),
|
||||
profile: Mutex::const_new(None),
|
||||
note_block_sound: Mutex::new(None),
|
||||
profile: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct StructureBlockBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -60,29 +59,58 @@ impl BlockEntity for StructureBlockBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
nbt.put_string("name", self.name.lock().await.clone());
|
||||
nbt.put_string("author", self.author.lock().await.clone());
|
||||
nbt.put_string("metadata", self.metadata.lock().await.clone());
|
||||
nbt.put_int("posX", *self.pos_x.lock().await);
|
||||
nbt.put_int("posY", *self.pos_y.lock().await);
|
||||
nbt.put_int("posZ", *self.pos_z.lock().await);
|
||||
nbt.put_int("sizeX", *self.size_x.lock().await);
|
||||
nbt.put_int("sizeY", *self.size_y.lock().await);
|
||||
nbt.put_int("sizeZ", *self.size_z.lock().await);
|
||||
nbt.put_string("rotation", self.rotation.lock().await.clone());
|
||||
nbt.put_string("mirror", self.mirror.lock().await.clone());
|
||||
nbt.put_string("mode", self.mode.lock().await.clone());
|
||||
nbt.put_bool("ignoreEntities", *self.ignore_entities.lock().await);
|
||||
nbt.put_bool("showAir", *self.show_air.lock().await);
|
||||
nbt.put_bool("showBoundingBox", *self.show_bounding_box.lock().await);
|
||||
nbt.put_float("integrity", *self.integrity.lock().await);
|
||||
nbt.put_long("seed", *self.seed.lock().await);
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(name) = self.name.lock() {
|
||||
nbt.put_string("name", name.clone());
|
||||
}
|
||||
if let Ok(author) = self.author.lock() {
|
||||
nbt.put_string("author", author.clone());
|
||||
}
|
||||
if let Ok(metadata) = self.metadata.lock() {
|
||||
nbt.put_string("metadata", metadata.clone());
|
||||
}
|
||||
if let Ok(pos_x) = self.pos_x.lock() {
|
||||
nbt.put_int("posX", *pos_x);
|
||||
}
|
||||
if let Ok(pos_y) = self.pos_y.lock() {
|
||||
nbt.put_int("posY", *pos_y);
|
||||
}
|
||||
if let Ok(pos_z) = self.pos_z.lock() {
|
||||
nbt.put_int("posZ", *pos_z);
|
||||
}
|
||||
if let Ok(size_x) = self.size_x.lock() {
|
||||
nbt.put_int("sizeX", *size_x);
|
||||
}
|
||||
if let Ok(size_y) = self.size_y.lock() {
|
||||
nbt.put_int("sizeY", *size_y);
|
||||
}
|
||||
if let Ok(size_z) = self.size_z.lock() {
|
||||
nbt.put_int("sizeZ", *size_z);
|
||||
}
|
||||
if let Ok(rotation) = self.rotation.lock() {
|
||||
nbt.put_string("rotation", rotation.clone());
|
||||
}
|
||||
if let Ok(mirror) = self.mirror.lock() {
|
||||
nbt.put_string("mirror", mirror.clone());
|
||||
}
|
||||
if let Ok(mode) = self.mode.lock() {
|
||||
nbt.put_string("mode", mode.clone());
|
||||
}
|
||||
if let Ok(ignore_entities) = self.ignore_entities.lock() {
|
||||
nbt.put_bool("ignoreEntities", *ignore_entities);
|
||||
}
|
||||
if let Ok(show_air) = self.show_air.lock() {
|
||||
nbt.put_bool("showAir", *show_air);
|
||||
}
|
||||
if let Ok(show_bounding_box) = self.show_bounding_box.lock() {
|
||||
nbt.put_bool("showBoundingBox", *show_bounding_box);
|
||||
}
|
||||
if let Ok(integrity) = self.integrity.lock() {
|
||||
nbt.put_float("integrity", *integrity);
|
||||
}
|
||||
if let Ok(seed) = self.seed.lock() {
|
||||
nbt.put_long("seed", *seed);
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use std::pin::Pin;
|
||||
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
|
||||
@ -25,12 +23,7 @@ impl BlockEntity for TestBlockBlockEntity {
|
||||
Self { position }
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
_nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
fn write_nbt(&self, _nbt: &mut NbtCompound) {}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use std::pin::Pin;
|
||||
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
|
||||
@ -25,12 +23,7 @@ impl BlockEntity for TestInstanceBlockBlockEntity {
|
||||
Self { position }
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
_nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
fn write_nbt(&self, _nbt: &mut NbtCompound) {}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct TrialSpawnerBlockEntity {
|
||||
pub position: BlockPos,
|
||||
@ -32,21 +31,22 @@ impl BlockEntity for TrialSpawnerBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if let Some(cfg) = self.normal_config.lock().await.as_ref() {
|
||||
nbt.put_compound("normal_config", cfg.clone());
|
||||
}
|
||||
if let Some(cfg) = self.ominous_config.lock().await.as_ref() {
|
||||
nbt.put_compound("ominous_config", cfg.clone());
|
||||
}
|
||||
if let Some(data) = self.spawner_data.lock().await.as_ref() {
|
||||
nbt.put_compound("spawner_data", data.clone());
|
||||
}
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(cfg) = self.normal_config.lock()
|
||||
&& let Some(cfg) = cfg.as_ref()
|
||||
{
|
||||
nbt.put_compound("normal_config", cfg.clone());
|
||||
}
|
||||
if let Ok(cfg) = self.ominous_config.lock()
|
||||
&& let Some(cfg) = cfg.as_ref()
|
||||
{
|
||||
nbt.put_compound("ominous_config", cfg.clone());
|
||||
}
|
||||
if let Ok(data) = self.spawner_data.lock()
|
||||
&& let Some(data) = data.as_ref()
|
||||
{
|
||||
nbt.put_compound("spawner_data", data.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
@ -77,12 +77,12 @@ impl BlockEntity for TrialSpawnerBlockEntity {
|
||||
impl TrialSpawnerBlockEntity {
|
||||
pub const ID: &'static str = "minecraft:trial_spawner";
|
||||
#[must_use]
|
||||
pub const fn new(position: BlockPos) -> Self {
|
||||
pub fn new(position: BlockPos) -> Self {
|
||||
Self {
|
||||
position,
|
||||
normal_config: Mutex::const_new(None),
|
||||
ominous_config: Mutex::const_new(None),
|
||||
spawner_data: Mutex::const_new(None),
|
||||
normal_config: Mutex::new(None),
|
||||
ominous_config: Mutex::new(None),
|
||||
spawner_data: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,8 +2,7 @@ use super::BlockEntity;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::collections::HashSet;
|
||||
use std::pin::Pin;
|
||||
use tokio::sync::Mutex;
|
||||
use std::sync::Mutex;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct VaultBlockEntity {
|
||||
@ -34,18 +33,17 @@ impl BlockEntity for VaultBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_nbt<'a>(
|
||||
&'a self,
|
||||
nbt: &'a mut NbtCompound,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if let Some(cfg) = self.config.lock().await.as_ref() {
|
||||
nbt.put_compound("config", cfg.clone());
|
||||
}
|
||||
if let Some(data) = self.server_data.lock().await.as_ref() {
|
||||
nbt.put_compound("server_data", data.clone());
|
||||
}
|
||||
})
|
||||
fn write_nbt(&self, nbt: &mut NbtCompound) {
|
||||
if let Ok(cfg) = self.config.lock()
|
||||
&& let Some(cfg) = cfg.as_ref()
|
||||
{
|
||||
nbt.put_compound("config", cfg.clone());
|
||||
}
|
||||
if let Ok(data) = self.server_data.lock()
|
||||
&& let Some(data) = data.as_ref()
|
||||
{
|
||||
nbt.put_compound("server_data", data.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn chunk_data_nbt(&self) -> Option<NbtCompound> {
|
||||
@ -82,10 +80,16 @@ impl VaultBlockEntity {
|
||||
}
|
||||
|
||||
pub fn has_rewarded(&self, player_id: &Uuid) -> bool {
|
||||
self.rewarded_players.blocking_lock().contains(player_id)
|
||||
self.rewarded_players
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.contains(player_id)
|
||||
}
|
||||
|
||||
pub fn mark_rewarded(&self, player_id: Uuid) {
|
||||
self.rewarded_players.blocking_lock().insert(player_id);
|
||||
self.rewarded_players
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
.insert(player_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,11 +180,7 @@ impl CommandExecutor for CloneExecutor {
|
||||
if should_clone {
|
||||
let block_entity_nbt = world.get_block_entity(&src_pos).map(|be| {
|
||||
let mut nbt = NbtCompound::new();
|
||||
if let Ok(handle) = tokio::runtime::Handle::try_current() {
|
||||
tokio::task::block_in_place(|| {
|
||||
handle.block_on(be.write_internal(&mut nbt));
|
||||
});
|
||||
}
|
||||
be.write_internal(&mut nbt);
|
||||
nbt
|
||||
});
|
||||
|
||||
|
||||
@ -2441,7 +2441,7 @@ impl Player {
|
||||
if player_pos != target_pos {
|
||||
self.living_entity.entity.set_pos(target_pos);
|
||||
if let Some(p) = self.world().get_player_by_uuid(self.gameprofile.id) {
|
||||
tokio::spawn(async move {
|
||||
server.runtime.spawn(async move {
|
||||
crate::world::chunker::update_position(&p).await;
|
||||
});
|
||||
}
|
||||
@ -2515,7 +2515,7 @@ impl Player {
|
||||
&& !chunk_of_chunks.is_empty()
|
||||
{
|
||||
let client = self.client.clone();
|
||||
tokio::spawn(async move {
|
||||
server.runtime.spawn(async move {
|
||||
client.send_chunks(&chunk_of_chunks).await;
|
||||
});
|
||||
if let ClientPlatform::Bedrock(bedrock_client) = self.client.as_ref()
|
||||
@ -2550,7 +2550,7 @@ impl Player {
|
||||
{
|
||||
let world_clone = p.world();
|
||||
let server_clone = world_clone.server.upgrade();
|
||||
tokio::spawn(async move {
|
||||
server.runtime.spawn(async move {
|
||||
let pos = *p.mining_pos.lock().await;
|
||||
let world = p.world();
|
||||
let state = world.get_block_state(&pos);
|
||||
|
||||
@ -426,18 +426,14 @@ impl PlayerAdvancement {
|
||||
result = true;
|
||||
self.progress_changed.insert(advancement);
|
||||
if !was_done && progress.is_done() {
|
||||
let player_c = player.clone();
|
||||
let adv_id = advancement.id.to_string();
|
||||
tokio::spawn(async move {
|
||||
if let Some(server) = player_c.world().server.upgrade() {
|
||||
let mut event =
|
||||
crate::plugin::api::events::player::player_advancement_done::PlayerAdvancementDoneEvent::new(
|
||||
player_c,
|
||||
adv_id,
|
||||
);
|
||||
server.plugin_manager.fire(&server, &mut event).await;
|
||||
}
|
||||
});
|
||||
if let Some(server) = player.world().server.upgrade() {
|
||||
let mut event =
|
||||
crate::plugin::api::events::player::player_advancement_done::PlayerAdvancementDoneEvent::new(
|
||||
player.clone(),
|
||||
advancement.id.to_string(),
|
||||
);
|
||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||
}
|
||||
Self::grant_reward(&player, advancement.reward);
|
||||
if let Some(display) = advancement.display
|
||||
&& display.announce_to_chat
|
||||
@ -448,24 +444,22 @@ impl PlayerAdvancement {
|
||||
.game_rules
|
||||
.show_advancement_messages
|
||||
{
|
||||
tokio::spawn(async move {
|
||||
let player_name = player.get_display_name();
|
||||
let je_component = TextComponent::translate(
|
||||
display.frame_type.get_translation(),
|
||||
[player_name.clone(), advancement.name()],
|
||||
);
|
||||
let je_packet = CSystemChatMessage::new(&je_component, false);
|
||||
let player_name = player.get_display_name();
|
||||
let je_component = TextComponent::translate(
|
||||
display.frame_type.get_translation(),
|
||||
[player_name.clone(), advancement.name()],
|
||||
);
|
||||
let je_packet = CSystemChatMessage::new(&je_component, false);
|
||||
|
||||
let be_packet = SText::translation(
|
||||
translation::bedrock::CHAT_TYPE_ACHIEVEMENT.to_string(),
|
||||
vec![
|
||||
player_name.0.to_bedrock_string(),
|
||||
display.get_title().0.to_bedrock_string(),
|
||||
],
|
||||
);
|
||||
let be_packet = SText::translation(
|
||||
translation::bedrock::CHAT_TYPE_ACHIEVEMENT.to_string(),
|
||||
vec![
|
||||
player_name.0.to_bedrock_string(),
|
||||
display.get_title().0.to_bedrock_string(),
|
||||
],
|
||||
);
|
||||
|
||||
player.world().broadcast_editioned(&je_packet, &be_packet);
|
||||
});
|
||||
player.world().broadcast_editioned(&je_packet, &be_packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -519,63 +519,56 @@ impl EntityBase for ArrowEntity {
|
||||
let is_spectral = entity.entity_type.id == EntityType::SPECTRAL_ARROW.id;
|
||||
let entity_type: &'static EntityType = entity.entity_type;
|
||||
let owner_id = self.owner_id;
|
||||
let target_clone = target.clone();
|
||||
let world_clone = world.clone();
|
||||
let pierce = self.pierce_level.load(Ordering::Relaxed);
|
||||
let damage_succeeded = target.damage_with_context(
|
||||
target.as_ref(),
|
||||
damage as f32,
|
||||
DamageType::ARROW,
|
||||
Some(hit_pos),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
tokio::spawn(async move {
|
||||
let damage_succeeded = target_clone.damage_with_context(
|
||||
&*target_clone,
|
||||
damage as f32,
|
||||
DamageType::ARROW,
|
||||
Some(hit_pos),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
if let Some(living) = target_clone.get_living_entity() {
|
||||
if punch > 0
|
||||
&& let Some(owner_id) = owner_id
|
||||
&& let Some(owner_entity) = world_clone.get_entity_by_id(owner_id)
|
||||
{
|
||||
crate::entity::combat::handle_knockback(
|
||||
owner_entity.get_entity(),
|
||||
target_clone.as_ref(),
|
||||
f64::from(punch) * 0.6,
|
||||
);
|
||||
}
|
||||
|
||||
// Play hit sound
|
||||
let sound_packet = CSoundEffect::new(
|
||||
IdOr::Id(Sound::EntityArrowHit as u16),
|
||||
SoundCategory::Neutral,
|
||||
&hit_pos,
|
||||
1.0,
|
||||
1.0,
|
||||
0.0,
|
||||
if let Some(living) = target.get_living_entity() {
|
||||
if punch > 0
|
||||
&& let Some(owner_id) = owner_id
|
||||
&& let Some(owner_entity) = world.get_entity_by_id(owner_id)
|
||||
{
|
||||
crate::entity::combat::handle_knockback(
|
||||
owner_entity.get_entity(),
|
||||
target.as_ref(),
|
||||
f64::from(punch) * 0.6,
|
||||
);
|
||||
world_clone.broadcast_packet_all(&sound_packet);
|
||||
}
|
||||
|
||||
if Self::should_apply_post_hurt_effects(damage_succeeded) {
|
||||
let item_stack = ItemStack::new(1, Self::default_item(entity_type));
|
||||
let scale = item_stack
|
||||
.get_data_component::<PotionDurationScaleImpl>()
|
||||
.map_or(1.0, |component| component.scale);
|
||||
crate::item::potion::PotionContents::apply_effects_to(
|
||||
living,
|
||||
crate::item::potion::PotionContents::read_potion_effects(
|
||||
&item_stack,
|
||||
),
|
||||
scale,
|
||||
crate::item::potion::PotionApplicationSource::Arrow,
|
||||
);
|
||||
// Play hit sound
|
||||
let sound_packet = CSoundEffect::new(
|
||||
IdOr::Id(Sound::EntityArrowHit as u16),
|
||||
SoundCategory::Neutral,
|
||||
&hit_pos,
|
||||
1.0,
|
||||
1.0,
|
||||
0.0,
|
||||
);
|
||||
world.broadcast_packet_all(&sound_packet);
|
||||
|
||||
if is_spectral {
|
||||
living.add_effect(Self::spectral_glowing_effect());
|
||||
}
|
||||
if Self::should_apply_post_hurt_effects(damage_succeeded) {
|
||||
let item_stack = ItemStack::new(1, Self::default_item(entity_type));
|
||||
let scale = item_stack
|
||||
.get_data_component::<PotionDurationScaleImpl>()
|
||||
.map_or(1.0, |component| component.scale);
|
||||
crate::item::potion::PotionContents::apply_effects_to(
|
||||
living,
|
||||
crate::item::potion::PotionContents::read_potion_effects(&item_stack),
|
||||
scale,
|
||||
crate::item::potion::PotionApplicationSource::Arrow,
|
||||
);
|
||||
|
||||
if is_spectral {
|
||||
living.add_effect(Self::spectral_glowing_effect());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Check pierce level
|
||||
if pierce == 0 {
|
||||
|
||||
@ -730,13 +730,9 @@ impl EntityBase for MinecartEntity {
|
||||
if let Some(container) = self.container()
|
||||
&& container.claim_drops()
|
||||
{
|
||||
let container_clone = container.clone();
|
||||
let world_clone = self.vehicle.entity.world.load_full();
|
||||
container_clone.unpack_loot();
|
||||
tokio::spawn(async move {
|
||||
let inventory: Arc<dyn Inventory> = container_clone;
|
||||
world_clone.scatter_inventory(&position, &inventory);
|
||||
});
|
||||
container.unpack_loot();
|
||||
let inventory: Arc<dyn Inventory> = container.clone();
|
||||
world.scatter_inventory(&position, &inventory);
|
||||
}
|
||||
if let Some(item) = self.drop_item() {
|
||||
world.drop_stack(&position, ItemStack::new(1, item));
|
||||
|
||||
@ -42,39 +42,35 @@ impl HopperMinecart {
|
||||
let world = entity.world.load();
|
||||
let pos = entity.pos.load();
|
||||
let source_pos = BlockPos::floored(pos.x, pos.y + 1.5, pos.z);
|
||||
let inventory = self.inventory.clone();
|
||||
let inventory = &self.inventory;
|
||||
let cart_box = entity.bounding_box.load().expand(0.25, 0.0, 0.25);
|
||||
let world_clone = world.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
if let Some(block_entity) = world_clone.get_block_entity(&source_pos)
|
||||
&& let Some(source) = block_entity.get_inventory()
|
||||
{
|
||||
for slot in 0..source.size() {
|
||||
let stack = source.get_stack(slot);
|
||||
if stack.is_empty() || !source.can_transfer_to(inventory.as_ref(), slot, &stack)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let backup = stack.clone();
|
||||
let one = source.remove_stack_specific(slot, 1);
|
||||
if HopperBlockEntity::add_one_item(source.as_ref(), inventory.as_ref(), &one) {
|
||||
return;
|
||||
}
|
||||
source.set_stack(slot, backup);
|
||||
if let Some(block_entity) = world.get_block_entity(&source_pos)
|
||||
&& let Some(source) = block_entity.get_inventory()
|
||||
{
|
||||
for slot in 0..source.size() {
|
||||
let stack = source.get_stack(slot);
|
||||
if stack.is_empty() || !source.can_transfer_to(inventory.as_ref(), slot, &stack) {
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
let backup = stack.clone();
|
||||
let one = source.remove_stack_specific(slot, 1);
|
||||
if HopperBlockEntity::add_one_item(source.as_ref(), inventory.as_ref(), &one) {
|
||||
return;
|
||||
}
|
||||
source.set_stack(slot, backup);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let suction_box = BoundingBox::new(
|
||||
Vector3::new(pos.x - 0.5, pos.y + 0.6875, pos.z - 0.5),
|
||||
Vector3::new(pos.x + 0.5, pos.y + 2.0, pos.z + 0.5),
|
||||
);
|
||||
if Self::pick_up_item_internal(&world_clone, &inventory, &suction_box) {
|
||||
return;
|
||||
}
|
||||
Self::pick_up_item_internal(&world_clone, &inventory, &cart_box);
|
||||
});
|
||||
let suction_box = BoundingBox::new(
|
||||
Vector3::new(pos.x - 0.5, pos.y + 0.6875, pos.z - 0.5),
|
||||
Vector3::new(pos.x + 0.5, pos.y + 2.0, pos.z + 0.5),
|
||||
);
|
||||
if Self::pick_up_item_internal(&world, inventory, &suction_box) {
|
||||
return;
|
||||
}
|
||||
Self::pick_up_item_internal(&world, inventory, &cart_box);
|
||||
}
|
||||
|
||||
fn pick_up_item_internal(
|
||||
|
||||
@ -42,9 +42,9 @@ impl VehicleEntity {
|
||||
self.entity.entity_id,
|
||||
);
|
||||
if let Some(server) = self.entity.world.load().server.upgrade() {
|
||||
tokio::spawn(async move {
|
||||
server.plugin_manager.fire(&server, &mut update_event).await;
|
||||
});
|
||||
server
|
||||
.plugin_manager
|
||||
.fire_blocking(&server, &mut update_event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,11 +22,28 @@ impl JavaClient {
|
||||
return;
|
||||
};
|
||||
|
||||
*jigsaw_block.name.lock().await = jigsaw.name.to_string();
|
||||
*jigsaw_block.target.lock().await = jigsaw.target.to_string();
|
||||
*jigsaw_block.pool.lock().await = jigsaw.pool.to_string();
|
||||
*jigsaw_block.final_state.lock().await = jigsaw.final_state.to_string();
|
||||
*jigsaw_block.joint.lock().await = JigsawJointType::from_str(jigsaw.joint);
|
||||
*jigsaw_block
|
||||
.name
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner) = jigsaw.name.to_string();
|
||||
*jigsaw_block
|
||||
.target
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner) = jigsaw.target.to_string();
|
||||
*jigsaw_block
|
||||
.pool
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner) = jigsaw.pool.to_string();
|
||||
*jigsaw_block
|
||||
.final_state
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner) =
|
||||
jigsaw.final_state.to_string();
|
||||
*jigsaw_block
|
||||
.joint
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner) =
|
||||
JigsawJointType::from_str(jigsaw.joint);
|
||||
jigsaw_block
|
||||
.selection_priority
|
||||
.store(jigsaw.selection_priority.0, Ordering::SeqCst);
|
||||
|
||||
@ -18,7 +18,7 @@ impl JavaClient {
|
||||
|
||||
let mut compound = NbtCompound::new();
|
||||
if let Some(block_entity) = player.world().get_block_entity(&packet.location) {
|
||||
block_entity.write_nbt(&mut compound).await;
|
||||
block_entity.write_nbt(&mut compound);
|
||||
}
|
||||
|
||||
let nbt_bytes = Nbt::new(String::new(), compound).write_unnamed();
|
||||
|
||||
@ -1225,7 +1225,7 @@ impl pumpkin::plugin::world::HostWorld for PluginHostState {
|
||||
};
|
||||
|
||||
let mut nbt = pumpkin_nbt::NbtCompound::new();
|
||||
entity.write_internal(&mut nbt).await;
|
||||
entity.write_internal(&mut nbt);
|
||||
|
||||
let bytes = pumpkin_nbt::Nbt::from(nbt).write_unnamed();
|
||||
Ok(Some(bytes.to_vec()))
|
||||
|
||||
@ -1083,7 +1083,9 @@ impl Server {
|
||||
all_players.extend(players.iter().cloned());
|
||||
}
|
||||
|
||||
let handle = self.runtime.clone();
|
||||
all_players.par_iter().for_each(|player| {
|
||||
let _guard = handle.enter();
|
||||
player.tick(self);
|
||||
});
|
||||
}
|
||||
|
||||
@ -481,7 +481,7 @@ impl World {
|
||||
.map(|chunk_block_entities| *chunk_block_entities.key())
|
||||
.collect();
|
||||
for chunk_pos in chunks {
|
||||
self.save_block_entities(&chunk_pos).await;
|
||||
self.save_block_entities(&chunk_pos);
|
||||
}
|
||||
|
||||
// Save portal POI to disk
|
||||
@ -520,7 +520,7 @@ impl World {
|
||||
/// `get_block_entity` takes the saved NBT out of the chunk when it wakes an
|
||||
/// entity up - so this has to run before the chunk is dropped, or everything
|
||||
/// the entity did since it was loaded is lost.
|
||||
async fn save_block_entities(&self, chunk_pos: &Vector2<i32>) {
|
||||
fn save_block_entities(&self, chunk_pos: &Vector2<i32>) {
|
||||
let Some(block_entities) = self
|
||||
.block_entities
|
||||
.get(chunk_pos)
|
||||
@ -531,7 +531,7 @@ impl World {
|
||||
|
||||
for block_entity in block_entities {
|
||||
let mut nbt = NbtCompound::new();
|
||||
block_entity.write_internal(&mut nbt).await;
|
||||
block_entity.write_internal(&mut nbt);
|
||||
if let Some(custom_data) = self
|
||||
.custom_block_entity_data
|
||||
.get(&block_entity.get_position())
|
||||
@ -1238,7 +1238,9 @@ impl World {
|
||||
);
|
||||
|
||||
let t_players = std::time::Instant::now();
|
||||
let player_handle = handle.clone();
|
||||
players.par_iter().for_each(|player| {
|
||||
let _guard = player_handle.enter();
|
||||
player.tick(server);
|
||||
});
|
||||
let player_elapsed = t_players.elapsed();
|
||||
@ -1664,7 +1666,7 @@ impl World {
|
||||
|
||||
// 3. Parallel Random Ticks via Rayon
|
||||
let world = self.clone();
|
||||
let random_handle = handle;
|
||||
let random_handle = handle.clone();
|
||||
tick_data
|
||||
.random_ticks
|
||||
.par_chunks(BATCH_SIZE)
|
||||
@ -1737,7 +1739,9 @@ impl World {
|
||||
spawning_chunks.shuffle(&mut rng());
|
||||
|
||||
let world = self.clone();
|
||||
let spawn_handle = handle.clone();
|
||||
spawning_chunks.par_chunks(8).for_each(|batch| {
|
||||
let _guard = spawn_handle.enter();
|
||||
let world = world.clone();
|
||||
let s_list = spawn_list.clone();
|
||||
let s_state = spawn_state.clone();
|
||||
@ -4930,7 +4934,7 @@ impl World {
|
||||
}
|
||||
|
||||
for chunk_pos in &chunks_set {
|
||||
self.save_block_entities(chunk_pos).await;
|
||||
self.save_block_entities(chunk_pos);
|
||||
self.block_entities.remove(chunk_pos);
|
||||
}
|
||||
}
|
||||
@ -6423,7 +6427,7 @@ impl World {
|
||||
.map(|chunk_block_entities| *chunk_block_entities.key())
|
||||
.collect();
|
||||
for chunk_pos in chunks {
|
||||
self.save_block_entities(&chunk_pos).await;
|
||||
self.save_block_entities(&chunk_pos);
|
||||
}
|
||||
|
||||
if let Ok(mut portal_poi) = self.portal_poi.try_lock() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user