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