remove async-trait entirely
This commit is contained in:
parent
ae751f3a83
commit
70b75a0ac5
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -1733,9 +1733,9 @@ checksum = "c505b3e17ed6b70a7ed2e67fbb2c560ee327353556120d6e72f5232b6880d536"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873"
|
||||
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
@ -2167,7 +2167,6 @@ dependencies = [
|
||||
name = "pumpkin"
|
||||
version = "0.1.0-dev+1.21.10"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"console-subscriber",
|
||||
@ -2252,7 +2251,6 @@ dependencies = [
|
||||
name = "pumpkin-inventory"
|
||||
version = "0.1.0-dev+1.21.10"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"crossbeam-utils",
|
||||
"log",
|
||||
"pumpkin-data",
|
||||
@ -2347,7 +2345,6 @@ dependencies = [
|
||||
name = "pumpkin-world"
|
||||
version = "0.1.0-dev+1.21.10"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bitflags",
|
||||
"bytes",
|
||||
"criterion",
|
||||
|
||||
@ -47,7 +47,5 @@ uuid = { version = "1.19", features = ["serde", "v3", "v4"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
async-trait = "0.1"
|
||||
|
||||
tempfile = { version = "3.23.0", default-features = false }
|
||||
proc-macro-error2 = "2"
|
||||
|
||||
@ -68,7 +68,6 @@ pub fn plugin_impl(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
|
||||
#input_struct
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl pumpkin::plugin::Plugin for #struct_ident {
|
||||
#(#methods)*
|
||||
}
|
||||
|
||||
@ -14,6 +14,5 @@ pumpkin-util = { path = "../pumpkin-util" }
|
||||
log.workspace = true
|
||||
tokio.workspace = true
|
||||
thiserror.workspace = true
|
||||
async-trait.workspace = true
|
||||
crossbeam-utils = "0.8.21"
|
||||
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
use std::sync::Arc;
|
||||
use std::{any::Any, pin::Pin};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_world::{inventory::split_stack, item::ItemStack};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use pumpkin_world::inventory::{Clearable, Inventory};
|
||||
use pumpkin_world::inventory::{Clearable, Inventory, InventoryFuture};
|
||||
|
||||
use super::recipes::RecipeInputInventory;
|
||||
|
||||
@ -32,13 +31,13 @@ impl CraftingInventory {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for CraftingInventory {
|
||||
fn size(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
for slot in self.items.iter() {
|
||||
if !slot.lock().await.is_empty() {
|
||||
return false;
|
||||
@ -46,25 +45,30 @@ impl Inventory for CraftingInventory {
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
self.items[slot].clone()
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move { self.items[slot].clone() })
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
let mut removed = ItemStack::EMPTY.clone();
|
||||
let mut guard = self.items[slot].lock().await;
|
||||
std::mem::swap(&mut removed, &mut *guard);
|
||||
removed
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
split_stack(&self.items, slot, amount).await
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move { split_stack(&self.items, slot, amount).await })
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
*self.items[slot].lock().await = stack;
|
||||
})
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
|
||||
@ -10,8 +10,8 @@ use crate::screen_handler::{
|
||||
InventoryPlayer, ItemStackFuture, ScreenHandler, ScreenHandlerBehaviour, ScreenHandlerFuture,
|
||||
ScreenHandlerListener,
|
||||
};
|
||||
use crate::slot::{NormalSlot, Slot};
|
||||
use async_trait::async_trait;
|
||||
use crate::slot::{BoxFuture, NormalSlot, Slot};
|
||||
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use pumpkin_data::recipes::{CraftingRecipeTypes, RECIPES_CRAFTING, RecipeResultStruct};
|
||||
use pumpkin_data::screen::WindowType;
|
||||
@ -324,7 +324,6 @@ impl ResultSlot {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Slot for ResultSlot {
|
||||
fn get_inventory(&self) -> Arc<dyn Inventory> {
|
||||
self.inventory.clone()
|
||||
@ -338,12 +337,23 @@ impl Slot for ResultSlot {
|
||||
self.id.store(id as u8, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
async fn on_quick_move_crafted(&self, _stack: ItemStack, _stack_prev: ItemStack) {
|
||||
fn on_quick_move_crafted(
|
||||
&self,
|
||||
_stack: ItemStack,
|
||||
_stack_prev: ItemStack,
|
||||
) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
// refill the result slot with the recipe result
|
||||
self.refill_output().await;
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_take_item(&self, player: &dyn InventoryPlayer, stack: &ItemStack) {
|
||||
fn on_take_item<'a>(
|
||||
&'a self,
|
||||
player: &'a dyn InventoryPlayer,
|
||||
stack: &'a ItemStack,
|
||||
) -> BoxFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
for i in 0..self.inventory.size() {
|
||||
let slot = self.inventory.get_stack(i).await;
|
||||
let mut stack = slot.lock().await;
|
||||
@ -354,37 +364,45 @@ impl Slot for ResultSlot {
|
||||
}
|
||||
self.stat_crafted(stack.item_count, player);
|
||||
self.mark_dirty().await;
|
||||
})
|
||||
}
|
||||
|
||||
async fn can_insert(&self, _stack: &ItemStack) -> bool {
|
||||
false
|
||||
fn can_insert(&self, _stack: &ItemStack) -> BoxFuture<'_, bool> {
|
||||
Box::pin(async move { false })
|
||||
}
|
||||
|
||||
async fn get_stack(&self) -> Arc<Mutex<ItemStack>> {
|
||||
self.result.clone()
|
||||
fn get_stack(&self) -> BoxFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move { self.result.clone() })
|
||||
}
|
||||
|
||||
async fn get_cloned_stack(&self) -> ItemStack {
|
||||
self.result.lock().await.clone()
|
||||
fn get_cloned_stack(&self) -> BoxFuture<'_, ItemStack> {
|
||||
Box::pin(async move { self.result.lock().await.clone() })
|
||||
}
|
||||
|
||||
async fn has_stack(&self) -> bool {
|
||||
!self.result.lock().await.is_empty()
|
||||
fn has_stack(&self) -> BoxFuture<'_, bool> {
|
||||
Box::pin(async move { !self.result.lock().await.is_empty() })
|
||||
}
|
||||
|
||||
async fn set_stack(&self, _stack: ItemStack) {
|
||||
fn set_stack(&self, _stack: ItemStack) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.refill_output().await;
|
||||
})
|
||||
}
|
||||
|
||||
async fn set_stack_prev(&self, _stack: ItemStack, _previous_stack: ItemStack) {
|
||||
fn set_stack_prev(&self, _stack: ItemStack, _previous_stack: ItemStack) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.refill_output().await;
|
||||
})
|
||||
}
|
||||
|
||||
async fn mark_dirty(&self) {
|
||||
fn mark_dirty(&self) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.inventory.mark_dirty();
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_max_item_count(&self) -> u8 {
|
||||
fn get_max_item_count(&self) -> BoxFuture<'_, u8> {
|
||||
Box::pin(async move {
|
||||
let mut count = u8::MAX;
|
||||
for i in 0..self.inventory.size() {
|
||||
let slot = self.inventory.get_stack(i).await;
|
||||
@ -394,9 +412,11 @@ impl Slot for ResultSlot {
|
||||
}
|
||||
}
|
||||
count
|
||||
})
|
||||
}
|
||||
|
||||
async fn take_stack(&self, _amount: u8) -> ItemStack {
|
||||
fn take_stack(&self, _amount: u8) -> BoxFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
if self.has_stack().await {
|
||||
let stack = self.result.lock().await;
|
||||
// Vanilla: net.minecraft.world.inventory.ResultContainer#removeItem
|
||||
@ -405,6 +425,7 @@ impl Slot for ResultSlot {
|
||||
} else {
|
||||
ItemStack::EMPTY.clone()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use std::{any::Any, pin::Pin, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_world::{
|
||||
inventory::{Clearable, Inventory},
|
||||
inventory::{Clearable, Inventory, InventoryFuture},
|
||||
item::ItemStack,
|
||||
};
|
||||
use tokio::sync::Mutex;
|
||||
@ -19,33 +18,37 @@ impl DoubleInventory {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for DoubleInventory {
|
||||
fn size(&self) -> usize {
|
||||
self.first.size() + self.second.size()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
self.first.is_empty().await && self.second.is_empty().await
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move { self.first.is_empty().await && self.second.is_empty().await })
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move {
|
||||
if slot >= self.first.size() {
|
||||
self.second.get_stack(slot - self.first.size()).await
|
||||
} else {
|
||||
self.first.get_stack(slot).await
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
if slot >= self.first.size() {
|
||||
self.second.remove_stack(slot - self.first.size()).await
|
||||
} else {
|
||||
self.first.remove_stack(slot).await
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
if slot >= self.first.size() {
|
||||
self.second
|
||||
.remove_stack_specific(slot - self.first.size(), amount)
|
||||
@ -53,18 +56,21 @@ impl Inventory for DoubleInventory {
|
||||
} else {
|
||||
self.first.remove_stack_specific(slot, amount).await
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn get_max_count_per_stack(&self) -> u8 {
|
||||
self.first.get_max_count_per_stack()
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
if slot >= self.first.size() {
|
||||
self.second.set_stack(slot - self.first.size(), stack).await
|
||||
} else {
|
||||
self.first.set_stack(slot, stack).await
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {
|
||||
@ -72,14 +78,18 @@ impl Inventory for DoubleInventory {
|
||||
self.second.mark_dirty();
|
||||
}
|
||||
|
||||
async fn on_open(&self) {
|
||||
fn on_open(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.first.on_open().await;
|
||||
self.second.on_open().await;
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_close(&self) {
|
||||
fn on_close(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.first.on_close().await;
|
||||
self.second.on_close().await;
|
||||
})
|
||||
}
|
||||
|
||||
fn is_valid_slot_for(&self, slot: usize, stack: &ItemStack) -> bool {
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
use std::sync::{Arc, atomic::AtomicU8};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::{fuels::is_fuel, item::Item};
|
||||
use pumpkin_world::inventory::Inventory;
|
||||
|
||||
use crate::slot::Slot;
|
||||
use crate::slot::{BoxFuture, Slot};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum FurnaceSlotType {
|
||||
@ -31,7 +30,6 @@ impl FurnaceSlot {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[async_trait]
|
||||
impl Slot for FurnaceSlot {
|
||||
fn get_inventory(&self) -> Arc<dyn Inventory> {
|
||||
self.inventory.clone()
|
||||
@ -46,15 +44,21 @@ impl Slot for FurnaceSlot {
|
||||
.store(id as u8, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
|
||||
async fn mark_dirty(&self) {
|
||||
fn mark_dirty(&self) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.inventory.mark_dirty();
|
||||
})
|
||||
}
|
||||
|
||||
async fn can_insert(&self, stack: &pumpkin_world::item::ItemStack) -> bool {
|
||||
fn can_insert<'a>(&'a self, stack: &'a pumpkin_world::item::ItemStack) -> BoxFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
match self.slot_type {
|
||||
FurnaceSlotType::Top => true,
|
||||
FurnaceSlotType::Bottom => is_fuel(stack.item.id) || stack.item.id == Item::BUCKET.id,
|
||||
FurnaceSlotType::Bottom => {
|
||||
is_fuel(stack.item.id) || stack.item.id == Item::BUCKET.id
|
||||
}
|
||||
FurnaceSlotType::Side => false,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
use std::{any::Any, array::from_fn, pin::Pin, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_world::{
|
||||
block::viewer::ViewerCountTracker,
|
||||
inventory::{Clearable, Inventory, split_stack},
|
||||
inventory::{Clearable, Inventory, InventoryFuture, split_stack},
|
||||
item::ItemStack,
|
||||
};
|
||||
use tokio::sync::Mutex;
|
||||
@ -46,13 +45,13 @@ impl EnderChestInventory {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for EnderChestInventory {
|
||||
fn size(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
for slot in self.items.iter() {
|
||||
if !slot.lock().await.is_empty() {
|
||||
return false;
|
||||
@ -60,37 +59,46 @@ impl Inventory for EnderChestInventory {
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
self.items[slot].clone()
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move { self.items[slot].clone() })
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
let mut removed = ItemStack::EMPTY.clone();
|
||||
let mut guard = self.items[slot].lock().await;
|
||||
std::mem::swap(&mut removed, &mut *guard);
|
||||
removed
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
split_stack(&self.items, slot, amount).await
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move { split_stack(&self.items, slot, amount).await })
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
*self.items[slot].lock().await = stack;
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_open(&self) {
|
||||
fn on_open(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
if let Some(tracker) = self.tracker.lock().await.as_ref() {
|
||||
tracker.open_container();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_close(&self) {
|
||||
fn on_close(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
if let Some(tracker) = self.tracker.lock().await.as_ref() {
|
||||
tracker.close_container();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
use crate::entity_equipment::EntityEquipment;
|
||||
use crate::screen_handler::InventoryPlayer;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use pumpkin_data::data_component_impl::EquipmentSlot;
|
||||
use pumpkin_protocol::java::client::play::CSetPlayerInventory;
|
||||
use pumpkin_util::Hand;
|
||||
use pumpkin_world::inventory::split_stack;
|
||||
use pumpkin_world::inventory::{Clearable, Inventory};
|
||||
use pumpkin_world::inventory::{InventoryFuture, split_stack};
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use std::any::Any;
|
||||
use std::array::from_fn;
|
||||
@ -320,13 +320,13 @@ impl Clearable for PlayerInventory {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for PlayerInventory {
|
||||
fn size(&self) -> usize {
|
||||
self.main_inventory.len() + self.equipment_slots.len()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
for item in self.main_inventory.iter() {
|
||||
if !item.lock().await.is_empty() {
|
||||
return false;
|
||||
@ -348,18 +348,22 @@ impl Inventory for PlayerInventory {
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move {
|
||||
if slot < self.main_inventory.len() {
|
||||
self.main_inventory[slot].clone()
|
||||
} else {
|
||||
let slot = self.equipment_slots.get(&slot).unwrap();
|
||||
self.entity_equipment.lock().await.get(slot)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
if slot < self.main_inventory.len() {
|
||||
split_stack(&self.main_inventory, slot, amount).await
|
||||
} else {
|
||||
@ -374,9 +378,11 @@ impl Inventory for PlayerInventory {
|
||||
|
||||
ItemStack::EMPTY.clone()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
if slot < self.main_inventory.len() {
|
||||
let mut removed = ItemStack::EMPTY.clone();
|
||||
let mut guard = self.main_inventory[slot].lock().await;
|
||||
@ -390,9 +396,11 @@ impl Inventory for PlayerInventory {
|
||||
.put(slot, ItemStack::EMPTY.clone())
|
||||
.await
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
if slot < self.main_inventory.len() {
|
||||
*self.main_inventory[slot].lock().await = stack;
|
||||
} else {
|
||||
@ -403,6 +411,7 @@ impl Inventory for PlayerInventory {
|
||||
None => log::warn!("Failed to get Equipment Slot at {slot}"),
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {}
|
||||
|
||||
@ -4,7 +4,6 @@ use crate::{
|
||||
slot::{NormalSlot, Slot},
|
||||
sync_handler::{SyncHandler, TrackedStack},
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use log::warn;
|
||||
use pumpkin_data::{
|
||||
data_component_impl::{EquipmentSlot, EquipmentType, EquippableImpl},
|
||||
@ -1038,14 +1037,17 @@ pub trait ScreenHandlerListener: Send + Sync {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
|
||||
pub type SharedScreenHandler = Arc<Mutex<dyn ScreenHandler>>;
|
||||
|
||||
pub trait ScreenHandlerFactory: Send + Sync {
|
||||
async fn create_screen_handler(
|
||||
&self,
|
||||
fn create_screen_handler<'a>(
|
||||
&'a self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<Arc<Mutex<dyn ScreenHandler>>>;
|
||||
player_inventory: &'a Arc<PlayerInventory>,
|
||||
player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, Option<SharedScreenHandler>>;
|
||||
fn get_display_name(&self) -> TextComponent;
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#![warn(unused)]
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
pin::Pin,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicU8, Ordering},
|
||||
@ -9,16 +10,17 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::screen_handler::InventoryPlayer;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use pumpkin_data::data_component_impl::EquipmentSlot;
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_world::inventory::Inventory;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use tokio::{sync::Mutex, time::timeout};
|
||||
|
||||
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
|
||||
// Slot.java
|
||||
// This is a trait due to crafting slots being a thing
|
||||
#[async_trait]
|
||||
pub trait Slot: Send + Sync + Debug {
|
||||
fn get_inventory(&self) -> Arc<dyn Inventory>;
|
||||
|
||||
@ -31,102 +33,148 @@ pub trait Slot: Send + Sync + Debug {
|
||||
/// locks to the stack to avoid deadlocks.
|
||||
///
|
||||
/// Also see: `ScreenHandler::quick_move`
|
||||
async fn on_quick_move_crafted(&self, _stack: ItemStack, _stack_prev: ItemStack) {}
|
||||
fn on_quick_move_crafted(
|
||||
&self,
|
||||
_stack: ItemStack,
|
||||
_stack_prev: ItemStack,
|
||||
) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {}) // Default implementation
|
||||
}
|
||||
|
||||
/// Callback for when an item is taken from the slot.
|
||||
///
|
||||
/// Also see: `safe_take`
|
||||
async fn on_take_item(&self, _player: &dyn InventoryPlayer, _stack: &ItemStack) {
|
||||
fn on_take_item<'a>(
|
||||
&'a self,
|
||||
_player: &'a dyn InventoryPlayer,
|
||||
_stack: &'a ItemStack,
|
||||
) -> BoxFuture<'a, ()> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
self.mark_dirty().await;
|
||||
})
|
||||
}
|
||||
|
||||
// Used for plugins
|
||||
async fn on_click(&self, _player: &dyn InventoryPlayer) {}
|
||||
|
||||
async fn can_insert(&self, _stack: &ItemStack) -> bool {
|
||||
true
|
||||
fn on_click(&self, _player: &dyn InventoryPlayer) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {}) // Default implementation
|
||||
}
|
||||
|
||||
async fn get_stack(&self) -> Arc<Mutex<ItemStack>> {
|
||||
self.get_inventory().get_stack(self.get_index()).await
|
||||
fn can_insert<'a>(&'a self, _stack: &'a ItemStack) -> BoxFuture<'a, bool> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move { true })
|
||||
}
|
||||
|
||||
async fn get_cloned_stack(&self) -> ItemStack {
|
||||
fn get_stack(&self) -> BoxFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move { self.get_inventory().get_stack(self.get_index()).await })
|
||||
}
|
||||
|
||||
fn get_cloned_stack(&self) -> BoxFuture<'_, ItemStack> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
let stack = self.get_stack().await;
|
||||
let lock = timeout(Duration::from_secs(5), stack.lock())
|
||||
.await
|
||||
.expect("Timed out while trying to acquire lock");
|
||||
|
||||
lock.clone()
|
||||
})
|
||||
}
|
||||
|
||||
async fn has_stack(&self) -> bool {
|
||||
fn has_stack(&self) -> BoxFuture<'_, bool> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
let inv = self.get_inventory();
|
||||
!inv.get_stack(self.get_index())
|
||||
.await
|
||||
.lock()
|
||||
.await
|
||||
.is_empty()
|
||||
})
|
||||
}
|
||||
|
||||
/// Make sure to drop any locks to the slot stack before calling this
|
||||
async fn set_stack(&self, stack: ItemStack) {
|
||||
fn set_stack(&self, stack: ItemStack) -> BoxFuture<'_, ()> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
self.set_stack_no_callbacks(stack).await;
|
||||
})
|
||||
}
|
||||
|
||||
/// Changes the stack in the slot with the given `stack`.
|
||||
async fn set_stack_prev(&self, stack: ItemStack, _previous_stack: ItemStack) {
|
||||
fn set_stack_prev(&self, stack: ItemStack, _previous_stack: ItemStack) -> BoxFuture<'_, ()> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
self.set_stack_no_callbacks(stack).await;
|
||||
})
|
||||
}
|
||||
|
||||
async fn set_stack_no_callbacks(&self, stack: ItemStack) {
|
||||
fn set_stack_no_callbacks(&self, stack: ItemStack) -> BoxFuture<'_, ()> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
let inv = self.get_inventory();
|
||||
inv.set_stack(self.get_index(), stack).await;
|
||||
self.mark_dirty().await;
|
||||
})
|
||||
}
|
||||
|
||||
async fn mark_dirty(&self);
|
||||
fn mark_dirty(&self) -> BoxFuture<'_, ()>; // This method must be implemented by concrete types
|
||||
|
||||
async fn get_max_item_count(&self) -> u8 {
|
||||
self.get_inventory().get_max_count_per_stack()
|
||||
fn get_max_item_count(&self) -> BoxFuture<'_, u8> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move { self.get_inventory().get_max_count_per_stack() })
|
||||
}
|
||||
|
||||
async fn get_max_item_count_for_stack(&self, stack: &ItemStack) -> u8 {
|
||||
fn get_max_item_count_for_stack<'a>(&'a self, stack: &'a ItemStack) -> BoxFuture<'a, u8> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
self.get_max_item_count()
|
||||
.await
|
||||
.min(stack.get_max_stack_size())
|
||||
})
|
||||
}
|
||||
|
||||
/// Removes a specific amount of items from the slot.
|
||||
///
|
||||
/// Mojang name: `remove`
|
||||
async fn take_stack(&self, amount: u8) -> ItemStack {
|
||||
fn take_stack(&self, amount: u8) -> BoxFuture<'_, ItemStack> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
let inv = self.get_inventory();
|
||||
|
||||
inv.remove_stack_specific(self.get_index(), amount).await
|
||||
})
|
||||
}
|
||||
|
||||
/// Mojang name: `mayPickup`
|
||||
async fn can_take_items(&self, _player: &dyn InventoryPlayer) -> bool {
|
||||
true
|
||||
fn can_take_items(&self, _player: &dyn InventoryPlayer) -> BoxFuture<'_, bool> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move { true })
|
||||
}
|
||||
|
||||
/// Mojang name: `allowModification`
|
||||
async fn allow_modification(&self, player: &dyn InventoryPlayer) -> bool {
|
||||
self.can_insert(&self.get_cloned_stack().await).await && self.can_take_items(player).await
|
||||
fn allow_modification<'a>(&'a self, player: &'a dyn InventoryPlayer) -> BoxFuture<'a, bool> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
self.can_insert(&self.get_cloned_stack().await).await
|
||||
&& self.can_take_items(player).await
|
||||
})
|
||||
}
|
||||
|
||||
/// Mojang name: `tryRemove`
|
||||
async fn try_take_stack_range(
|
||||
&self,
|
||||
fn try_take_stack_range<'a>(
|
||||
&'a self,
|
||||
min: u8,
|
||||
max: u8,
|
||||
player: &dyn InventoryPlayer,
|
||||
) -> Option<ItemStack> {
|
||||
player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, Option<ItemStack>> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
if !self.can_take_items(player).await {
|
||||
return None;
|
||||
}
|
||||
if !self.allow_modification(player).await && self.get_cloned_stack().await.item_count > max
|
||||
if !self.allow_modification(player).await
|
||||
&& self.get_cloned_stack().await.item_count > max
|
||||
{
|
||||
// If the slot is not allowed to be modified, we cannot take a partial stack from it.
|
||||
return None;
|
||||
@ -144,13 +192,20 @@ pub trait Slot: Send + Sync + Debug {
|
||||
|
||||
Some(stack)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Safely tries to take a stack of items from the slot, returning `None` if the stack is empty.
|
||||
/// Considering such as result slots, as their stacks cannot split.
|
||||
///
|
||||
/// Mojang name: `safeTake`
|
||||
async fn safe_take(&self, min: u8, max: u8, player: &dyn InventoryPlayer) -> ItemStack {
|
||||
fn safe_take<'a>(
|
||||
&'a self,
|
||||
min: u8,
|
||||
max: u8,
|
||||
player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, ItemStack> {
|
||||
Box::pin(async move {
|
||||
let stack = self.try_take_stack_range(min, max, player).await;
|
||||
|
||||
if let Some(stack) = &stack {
|
||||
@ -158,14 +213,20 @@ pub trait Slot: Send + Sync + Debug {
|
||||
}
|
||||
|
||||
stack.unwrap_or(ItemStack::EMPTY.clone())
|
||||
})
|
||||
}
|
||||
|
||||
async fn insert_stack(&self, stack: ItemStack) -> ItemStack {
|
||||
fn insert_stack(&self, stack: ItemStack) -> BoxFuture<'_, ItemStack> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
let stack_item_count = stack.item_count;
|
||||
self.insert_stack_count(stack, stack_item_count).await
|
||||
})
|
||||
}
|
||||
|
||||
async fn insert_stack_count(&self, mut stack: ItemStack, count: u8) -> ItemStack {
|
||||
fn insert_stack_count(&self, mut stack: ItemStack, count: u8) -> BoxFuture<'_, ItemStack> {
|
||||
// Default implementation logic:
|
||||
Box::pin(async move {
|
||||
if !stack.is_empty() && self.can_insert(&stack).await {
|
||||
let stack_mutex = self.get_stack().await;
|
||||
let mut stack_self = stack_mutex.lock().await;
|
||||
@ -174,7 +235,7 @@ pub trait Slot: Send + Sync + Debug {
|
||||
.min(self.get_max_item_count_for_stack(&stack).await - stack_self.item_count);
|
||||
|
||||
if min_count == 0 {
|
||||
return stack;
|
||||
stack
|
||||
} else {
|
||||
if stack_self.is_empty() {
|
||||
drop(stack_self);
|
||||
@ -187,11 +248,12 @@ pub trait Slot: Send + Sync + Debug {
|
||||
self.set_stack(cloned_stack).await;
|
||||
}
|
||||
|
||||
return stack;
|
||||
stack
|
||||
}
|
||||
} else {
|
||||
stack
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,7 +274,6 @@ impl NormalSlot {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[async_trait]
|
||||
impl Slot for NormalSlot {
|
||||
fn get_inventory(&self) -> Arc<dyn Inventory> {
|
||||
self.inventory.clone()
|
||||
@ -226,8 +287,10 @@ impl Slot for NormalSlot {
|
||||
self.id.store(id as u8, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
async fn mark_dirty(&self) {
|
||||
fn mark_dirty(&self) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.inventory.mark_dirty();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,7 +314,6 @@ impl ArmorSlot {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Slot for ArmorSlot {
|
||||
fn get_inventory(&self) -> Arc<dyn Inventory> {
|
||||
self.inventory.clone()
|
||||
@ -265,16 +327,19 @@ impl Slot for ArmorSlot {
|
||||
self.id.store(id as u8, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
async fn get_max_item_count(&self) -> u8 {
|
||||
1
|
||||
fn get_max_item_count(&self) -> BoxFuture<'_, u8> {
|
||||
Box::pin(async move { 1 })
|
||||
}
|
||||
|
||||
async fn set_stack_prev(&self, stack: ItemStack, _previous_stack: ItemStack) {
|
||||
fn set_stack_prev(&self, stack: ItemStack, _previous_stack: ItemStack) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
//TODO: this.entity.onEquipStack(this.equipmentSlot, previousStack, stack);
|
||||
self.set_stack_no_callbacks(stack).await;
|
||||
})
|
||||
}
|
||||
|
||||
async fn can_insert(&self, stack: &ItemStack) -> bool {
|
||||
fn can_insert<'a>(&'a self, stack: &'a ItemStack) -> BoxFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
match self.equipment_slot {
|
||||
EquipmentSlot::Head(_) => {
|
||||
stack.is_helmet() || stack.is_skull() || stack.item == &Item::CARVED_PUMPKIN
|
||||
@ -284,14 +349,19 @@ impl Slot for ArmorSlot {
|
||||
EquipmentSlot::Feet(_) => stack.is_boots(),
|
||||
_ => true,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn can_take_items(&self, _player: &dyn InventoryPlayer) -> bool {
|
||||
fn can_take_items(&self, _player: &dyn InventoryPlayer) -> BoxFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
// TODO: Check enchantments
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn mark_dirty(&self) {
|
||||
fn mark_dirty(&self) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.inventory.mark_dirty();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,6 @@ pumpkin-util = { path = "../pumpkin-util" }
|
||||
pumpkin-config = { path = "../pumpkin-config" }
|
||||
pumpkin-data = { path = "../pumpkin-data" }
|
||||
|
||||
async-trait.workspace = true
|
||||
futures.workspace = true
|
||||
|
||||
bytes.workspace = true
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// use std::{fs, path::PathBuf, sync::Arc};
|
||||
//
|
||||
// use async_trait::async_trait;
|
||||
//
|
||||
// use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
|
||||
// use pumpkin_data::BlockDirection;
|
||||
// use pumpkin_util::math::{position::BlockPos, vector2::Vector2};
|
||||
@ -79,7 +79,6 @@
|
||||
//
|
||||
// struct BlockRegistry;
|
||||
//
|
||||
// #[async_trait]
|
||||
// impl BlockRegistryExt for BlockRegistry {
|
||||
// fn can_place_at(
|
||||
// &self,
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::block_properties::{BarrelLikeProperties, BlockProperties};
|
||||
use pumpkin_data::sound::{Sound, SoundCategory};
|
||||
use pumpkin_data::{Block, FacingExt};
|
||||
@ -19,6 +18,7 @@ use std::{
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::block::viewer::{ViewerCountListener, ViewerCountTracker, ViewerFuture};
|
||||
use crate::inventory::InventoryFuture;
|
||||
use crate::world::{BlockFlags, SimpleWorld};
|
||||
use crate::{
|
||||
inventory::{
|
||||
@ -175,13 +175,13 @@ impl BarrelBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for BarrelBlockEntity {
|
||||
fn size(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
for slot in self.items.iter() {
|
||||
if !slot.lock().await.is_empty() {
|
||||
return false;
|
||||
@ -189,33 +189,42 @@ impl Inventory for BarrelBlockEntity {
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
self.items[slot].clone()
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move { self.items[slot].clone() })
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
let mut removed = ItemStack::EMPTY.clone();
|
||||
let mut guard = self.items[slot].lock().await;
|
||||
std::mem::swap(&mut removed, &mut *guard);
|
||||
removed
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
split_stack(&self.items, slot, amount).await
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move { split_stack(&self.items, slot, amount).await })
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
*self.items[slot].lock().await = stack;
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_open(&self) {
|
||||
fn on_open(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.viewers.open_container();
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_close(&self) {
|
||||
fn on_close(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.viewers.close_container();
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {
|
||||
|
||||
@ -8,7 +8,6 @@ use std::{
|
||||
},
|
||||
};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::{
|
||||
Block, HorizontalFacingExt,
|
||||
block_properties::{BlockProperties, ChestLikeProperties, ChestType},
|
||||
@ -23,7 +22,7 @@ use tokio::sync::Mutex;
|
||||
|
||||
use crate::{
|
||||
block::viewer::{ViewerCountListener, ViewerCountTracker, ViewerFuture},
|
||||
inventory::{Clearable, Inventory, split_stack},
|
||||
inventory::{Clearable, Inventory, InventoryFuture, split_stack},
|
||||
item::ItemStack,
|
||||
world::SimpleWorld,
|
||||
};
|
||||
@ -183,13 +182,13 @@ impl ChestBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for ChestBlockEntity {
|
||||
fn size(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
for slot in self.items.iter() {
|
||||
if !slot.lock().await.is_empty() {
|
||||
return false;
|
||||
@ -197,33 +196,42 @@ impl Inventory for ChestBlockEntity {
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
self.items[slot].clone()
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move { self.items[slot].clone() })
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
let mut removed = ItemStack::EMPTY.clone();
|
||||
let mut guard = self.items[slot].lock().await;
|
||||
std::mem::swap(&mut removed, &mut *guard);
|
||||
removed
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
split_stack(&self.items, slot, amount).await
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move { split_stack(&self.items, slot, amount).await })
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
*self.items[slot].lock().await = stack;
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_open(&self) {
|
||||
fn on_open(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.viewers.open_container();
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_close(&self) {
|
||||
fn on_close(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.viewers.close_container();
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use async_trait::async_trait;
|
||||
use log::warn;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::block_properties::{BlockProperties, ChiseledBookshelfLikeProperties};
|
||||
@ -15,6 +14,7 @@ use std::{
|
||||
};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::inventory::InventoryFuture;
|
||||
use crate::{
|
||||
block::entities::BlockEntity,
|
||||
inventory::{Clearable, Inventory, split_stack},
|
||||
@ -130,13 +130,13 @@ impl ChiseledBookshelfBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for ChiseledBookshelfBlockEntity {
|
||||
fn size(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
for slot in self.items.iter() {
|
||||
if !slot.lock().await.is_empty() {
|
||||
return false;
|
||||
@ -144,25 +144,30 @@ impl Inventory for ChiseledBookshelfBlockEntity {
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
self.items[slot].clone()
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move { self.items[slot].clone() })
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
let mut removed = ItemStack::EMPTY.clone();
|
||||
let mut guard = self.items[slot].lock().await;
|
||||
std::mem::swap(&mut removed, &mut *guard);
|
||||
removed
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
split_stack(&self.items, slot, amount).await
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move { split_stack(&self.items, slot, amount).await })
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
*self.items[slot].lock().await = stack;
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use crate::block::entities::BlockEntity;
|
||||
use crate::inventory::{Clearable, Inventory, split_stack};
|
||||
use crate::inventory::{Clearable, Inventory, InventoryFuture, split_stack};
|
||||
use crate::item::ItemStack;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use rand::{Rng, rng};
|
||||
@ -95,13 +94,13 @@ impl DropperBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for DropperBlockEntity {
|
||||
fn size(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
for slot in self.items.iter() {
|
||||
if !slot.lock().await.is_empty() {
|
||||
return false;
|
||||
@ -109,25 +108,30 @@ impl Inventory for DropperBlockEntity {
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
self.items[slot].clone()
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move { self.items[slot].clone() })
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
let mut removed = ItemStack::EMPTY.clone();
|
||||
let mut guard = self.items[slot].lock().await;
|
||||
std::mem::swap(&mut removed, &mut *guard);
|
||||
removed
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
split_stack(&self.items, slot, amount).await
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move { split_stack(&self.items, slot, amount).await })
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
*self.items[slot].lock().await = stack;
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {
|
||||
|
||||
@ -7,7 +7,6 @@ use std::{
|
||||
},
|
||||
};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::{
|
||||
block_properties::{BlockProperties, FurnaceLikeProperties},
|
||||
fuels::get_item_burn_ticks,
|
||||
@ -20,7 +19,7 @@ use pumpkin_util::math::position::BlockPos;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::{
|
||||
inventory::{Clearable, Inventory, split_stack},
|
||||
inventory::{Clearable, Inventory, InventoryFuture, split_stack},
|
||||
item::ItemStack,
|
||||
world::{BlockFlags, SimpleWorld},
|
||||
};
|
||||
@ -375,13 +374,13 @@ impl FurnaceBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for FurnaceBlockEntity {
|
||||
fn size(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
for slot in self.items.iter() {
|
||||
if !slot.lock().await.is_empty() {
|
||||
return false;
|
||||
@ -389,29 +388,33 @@ impl Inventory for FurnaceBlockEntity {
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
self.items[slot].clone()
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move { self.items[slot].clone() })
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
let mut removed = ItemStack::EMPTY.clone();
|
||||
let mut guard = self.items[slot].lock().await;
|
||||
std::mem::swap(&mut removed, &mut *guard);
|
||||
removed
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
split_stack(&self.items, slot, amount).await
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move { split_stack(&self.items, slot, amount).await })
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
let furnace_stack = self.get_stack(slot).await;
|
||||
let mut furnace_stack = furnace_stack.lock().await;
|
||||
|
||||
let is_same_item =
|
||||
!stack.is_empty() && ItemStack::are_items_and_components_equal(&furnace_stack, &stack);
|
||||
let is_same_item = !stack.is_empty()
|
||||
&& ItemStack::are_items_and_components_equal(&furnace_stack, &stack);
|
||||
|
||||
*furnace_stack = stack.clone();
|
||||
drop(furnace_stack);
|
||||
@ -426,6 +429,7 @@ impl Inventory for FurnaceBlockEntity {
|
||||
self.cooking_time_spent.store(0, Ordering::Relaxed);
|
||||
self.mark_dirty();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
use crate::BlockStateId;
|
||||
use crate::block::entities::BlockEntity;
|
||||
use crate::inventory::{Clearable, Inventory, split_stack};
|
||||
use crate::inventory::{Clearable, Inventory, InventoryFuture, split_stack};
|
||||
use crate::item::ItemStack;
|
||||
use crate::world::SimpleWorld;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::block_properties::{BlockProperties, HopperFacing, HopperLikeProperties};
|
||||
use pumpkin_data::tag::Taggable;
|
||||
use pumpkin_data::{Block, tag};
|
||||
@ -294,13 +293,13 @@ impl HopperBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for HopperBlockEntity {
|
||||
fn size(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
for slot in self.items.iter() {
|
||||
if !slot.lock().await.is_empty() {
|
||||
return false;
|
||||
@ -308,25 +307,30 @@ impl Inventory for HopperBlockEntity {
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
self.items[slot].clone()
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move { self.items[slot].clone() })
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
let mut removed = ItemStack::EMPTY.clone();
|
||||
let mut guard = self.items[slot].lock().await;
|
||||
std::mem::swap(&mut removed, &mut *guard);
|
||||
removed
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
split_stack(&self.items, slot, amount).await
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move { split_stack(&self.items, slot, amount).await })
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
*self.items[slot].lock().await = stack;
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::sound::{Sound, SoundCategory};
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
@ -6,6 +5,7 @@ use pumpkin_util::random::xoroshiro128::Xoroshiro;
|
||||
use pumpkin_util::random::{RandomImpl, get_seed};
|
||||
use std::any::Any;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::{
|
||||
array::from_fn,
|
||||
sync::{Arc, atomic::AtomicBool},
|
||||
@ -13,6 +13,7 @@ use std::{
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::block::viewer::{ViewerCountListener, ViewerCountTracker, ViewerFuture};
|
||||
use crate::inventory::InventoryFuture;
|
||||
use crate::world::SimpleWorld;
|
||||
use crate::{
|
||||
inventory::{
|
||||
@ -175,13 +176,13 @@ impl ShulkerBoxBlockEntity {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Inventory for ShulkerBoxBlockEntity {
|
||||
fn size(&self) -> usize {
|
||||
self.items.len()
|
||||
}
|
||||
|
||||
async fn is_empty(&self) -> bool {
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool> {
|
||||
Box::pin(async move {
|
||||
for slot in self.items.iter() {
|
||||
if !slot.lock().await.is_empty() {
|
||||
return false;
|
||||
@ -189,37 +190,46 @@ impl Inventory for ShulkerBoxBlockEntity {
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>> {
|
||||
self.items[slot].clone()
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>> {
|
||||
Box::pin(async move { self.items[slot].clone() })
|
||||
}
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack {
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move {
|
||||
let mut removed = ItemStack::EMPTY.clone();
|
||||
let mut guard = self.items[slot].lock().await;
|
||||
std::mem::swap(&mut removed, &mut *guard);
|
||||
removed
|
||||
})
|
||||
}
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack {
|
||||
split_stack(&self.items, slot, amount).await
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack> {
|
||||
Box::pin(async move { split_stack(&self.items, slot, amount).await })
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack) {
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
*self.items[slot].lock().await = stack;
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_open(&self) {
|
||||
fn on_open(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.viewers.open_container();
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_close(&self) {
|
||||
fn on_close(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.viewers.close_container();
|
||||
})
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {
|
||||
self.dirty.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
self.dirty.store(true, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
use async_trait::async_trait;
|
||||
use bytes::*;
|
||||
use flate2::read::{GzDecoder, GzEncoder, ZlibDecoder, ZlibEncoder};
|
||||
use itertools::Itertools;
|
||||
@ -526,7 +525,6 @@ pub trait SingleChunkDataSerializer: Send + Sync + Sized + Dirtiable {
|
||||
fn position(&self) -> &Vector2<i32>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<S: SingleChunkDataSerializer> ChunkSerializer for AnvilChunkFile<S> {
|
||||
type Data = S;
|
||||
type WriteBackend = PathBuf;
|
||||
@ -827,7 +825,7 @@ impl<S: SingleChunkDataSerializer> ChunkSerializer for AnvilChunkFile<S> {
|
||||
/*
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use async_trait::async_trait;
|
||||
|
||||
use pumpkin_config::{AdvancedConfiguration, advanced_config, override_config_for_testing};
|
||||
use pumpkin_data::BlockDirection;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
@ -849,7 +847,6 @@ mod tests {
|
||||
|
||||
struct BlockRegistry;
|
||||
|
||||
#[async_trait]
|
||||
impl BlockRegistryExt for BlockRegistry {
|
||||
fn can_place_at(
|
||||
&self,
|
||||
|
||||
@ -6,7 +6,6 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use crate::chunk::format::anvil::{AnvilChunkFile, SingleChunkDataSerializer};
|
||||
use crate::chunk::io::{ChunkSerializer, LoadedData};
|
||||
use crate::chunk::{ChunkReadingError, ChunkWritingError};
|
||||
use async_trait::async_trait;
|
||||
use bytes::{Buf, BufMut, Bytes};
|
||||
use log::error;
|
||||
use pumpkin_util::math::vector2::Vector2;
|
||||
@ -163,7 +162,6 @@ impl<S: SingleChunkDataSerializer> Default for LinearFile<S> {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<S: SingleChunkDataSerializer> ChunkSerializer for LinearFile<S> {
|
||||
type Data = S;
|
||||
type WriteBackend = PathBuf;
|
||||
@ -372,7 +370,7 @@ impl<S: SingleChunkDataSerializer> ChunkSerializer for LinearFile<S> {
|
||||
/*
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use async_trait::async_trait;
|
||||
|
||||
use core::panic;
|
||||
use pumpkin_data::BlockDirection;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
@ -394,7 +392,6 @@ mod tests {
|
||||
|
||||
struct BlockRegistry;
|
||||
|
||||
#[async_trait]
|
||||
impl BlockRegistryExt for BlockRegistry {
|
||||
fn can_place_at(
|
||||
&self,
|
||||
|
||||
@ -6,7 +6,6 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use futures::future::join_all;
|
||||
use log::{error, trace};
|
||||
use num_traits::Zero;
|
||||
@ -18,7 +17,10 @@ use tokio::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
chunk::{ChunkReadingError, ChunkWritingError, io::Dirtiable},
|
||||
chunk::{
|
||||
ChunkReadingError, ChunkWritingError,
|
||||
io::{BoxFuture, Dirtiable},
|
||||
},
|
||||
level::LevelFolder,
|
||||
};
|
||||
|
||||
@ -149,7 +151,6 @@ impl<S: ChunkSerializer<WriteBackend = PathBuf>> ChunkFileManager<S> {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<P, S> FileIO for ChunkFileManager<S>
|
||||
where
|
||||
P: PathFromLevelFolder + Send + Sync + Sized + Dirtiable + 'static,
|
||||
@ -157,7 +158,13 @@ where
|
||||
{
|
||||
type Data = Arc<RwLock<S::Data>>;
|
||||
|
||||
async fn watch_chunks(&self, folder: &LevelFolder, chunks: &[Vector2<i32>]) {
|
||||
// Changed: Return BoxFuture<()>
|
||||
fn watch_chunks<'a>(
|
||||
&'a self,
|
||||
folder: &'a LevelFolder,
|
||||
chunks: &'a [Vector2<i32>],
|
||||
) -> BoxFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
// It is intentional that regions are watched multiple times (once per chunk)
|
||||
let mut watchers = self.watchers.write().await;
|
||||
for chunk in chunks {
|
||||
@ -172,9 +179,16 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn unwatch_chunks(&self, folder: &LevelFolder, chunks: &[Vector2<i32>]) {
|
||||
// Changed: Return BoxFuture<()>
|
||||
fn unwatch_chunks<'a>(
|
||||
&'a self,
|
||||
folder: &'a LevelFolder,
|
||||
chunks: &'a [Vector2<i32>],
|
||||
) -> BoxFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let mut watchers = self.watchers.write().await;
|
||||
for chunk in chunks {
|
||||
let key = S::get_chunk_key(chunk);
|
||||
@ -189,18 +203,24 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn clear_watched_chunks(&self) {
|
||||
// Changed: Return BoxFuture<()>
|
||||
fn clear_watched_chunks(&self) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
self.watchers.write().await.clear();
|
||||
})
|
||||
}
|
||||
|
||||
async fn fetch_chunks(
|
||||
&self,
|
||||
folder: &LevelFolder,
|
||||
chunk_coords: &[Vector2<i32>],
|
||||
// Changed: Return BoxFuture<()>
|
||||
fn fetch_chunks<'a>(
|
||||
&'a self,
|
||||
folder: &'a LevelFolder,
|
||||
chunk_coords: &'a [Vector2<i32>],
|
||||
stream: tokio::sync::mpsc::Sender<LoadedData<Self::Data, ChunkReadingError>>,
|
||||
) {
|
||||
) -> BoxFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let mut regions_chunks: BTreeMap<String, Vec<Vector2<i32>>> = BTreeMap::new();
|
||||
|
||||
for at in chunk_coords {
|
||||
@ -214,7 +234,10 @@ where
|
||||
|
||||
// we use a Sync Closure with an Async Block to execute the tasks concurrently
|
||||
// Also improves File Cache utilizations.
|
||||
let region_read_tasks = regions_chunks.into_iter().map(async |(file_name, chunks)| {
|
||||
let region_read_tasks = regions_chunks.into_iter().map(move |(file_name, chunks)| {
|
||||
let task_stream = stream.clone();
|
||||
|
||||
async move {
|
||||
let path = P::file_path(folder, &file_name);
|
||||
let chunk_serializer = match self.get_serializer(&path).await {
|
||||
Ok(chunk_serializer) => chunk_serializer,
|
||||
@ -222,18 +245,20 @@ where
|
||||
unreachable!("Default Serializer must be created")
|
||||
}
|
||||
Err(err) => {
|
||||
let _ = stream.send(LoadedData::Error((chunks[0], err))).await;
|
||||
let _ = task_stream.send(LoadedData::Error((chunks[0], err))).await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Intermediate channel for wrapping the data with the Arc<RwLock>
|
||||
let (send, mut recv) = mpsc::channel::<LoadedData<S::Data, ChunkReadingError>>(1);
|
||||
let (send, mut recv) =
|
||||
mpsc::channel::<LoadedData<S::Data, ChunkReadingError>>(1);
|
||||
|
||||
let intermediary = async {
|
||||
let intermediary = async move {
|
||||
// Note: 'task_stream' is captured and moved here
|
||||
while let Some(data) = recv.recv().await {
|
||||
let wrapped_data = data.map_loaded(|data| Arc::new(RwLock::new(data)));
|
||||
if stream.send(wrapped_data).await.is_err() {
|
||||
if task_stream.send(wrapped_data).await.is_err() {
|
||||
// Stream is closed, so stop unneeded computation and io
|
||||
return;
|
||||
}
|
||||
@ -248,16 +273,20 @@ where
|
||||
};
|
||||
|
||||
join!(intermediary, reader);
|
||||
}
|
||||
});
|
||||
|
||||
let _ = join_all(region_read_tasks).await;
|
||||
})
|
||||
}
|
||||
|
||||
async fn save_chunks(
|
||||
&self,
|
||||
folder: &LevelFolder,
|
||||
// Changed: Return BoxFuture<Result<(), ChunkWritingError>>
|
||||
fn save_chunks<'a>(
|
||||
&'a self,
|
||||
folder: &'a LevelFolder,
|
||||
chunks_data: Vec<(Vector2<i32>, Self::Data)>,
|
||||
) -> Result<(), ChunkWritingError> {
|
||||
) -> BoxFuture<'a, Result<(), ChunkWritingError>> {
|
||||
Box::pin(async move {
|
||||
let mut regions_chunks: BTreeMap<String, Vec<Self::Data>> = BTreeMap::new();
|
||||
|
||||
for (at, chunk) in chunks_data {
|
||||
@ -277,7 +306,8 @@ where
|
||||
// with out waiting the future. Also it improve we File Cache utilizations.
|
||||
let tasks = regions_chunks
|
||||
.into_iter()
|
||||
.map(async |(file_name, chunk_locks)| {
|
||||
// The closure now needs `move` to capture `self` and `folder` by value
|
||||
.map(move |(file_name, chunk_locks)| async move {
|
||||
let path = P::file_path(folder, &file_name);
|
||||
log::trace!("Updating data for file {}", path.display());
|
||||
|
||||
@ -290,9 +320,7 @@ where
|
||||
error!("Error reading the data before write: {err}");
|
||||
Err(ChunkWritingError::IoError(err))
|
||||
}
|
||||
Err(_) => {
|
||||
Err(ChunkWritingError::IoError(std::io::ErrorKind::Other))
|
||||
}
|
||||
Err(_) => Err(ChunkWritingError::IoError(std::io::ErrorKind::Other)),
|
||||
}?;
|
||||
|
||||
// Create a task for each chunk_lock
|
||||
@ -375,24 +403,31 @@ where
|
||||
let _test: Vec<Result<(), ChunkWritingError>> = join_all(tasks).await;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
async fn clean_up_log(&self) {
|
||||
// Changed: Return BoxFuture<()>
|
||||
fn clean_up_log(&self) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
let locks = self.file_locks.read().await;
|
||||
log::debug!("{} File locks remain in cache", locks.len());
|
||||
})
|
||||
}
|
||||
|
||||
async fn block_and_await_ongoing_tasks(&self) {
|
||||
// Changed: Return BoxFuture<()>
|
||||
fn block_and_await_ongoing_tasks(&self) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {
|
||||
//we need to block any other operation
|
||||
let serializer_cache = self.file_locks.write().await;
|
||||
|
||||
// Acquire a write lock on all entries to verify they are complete
|
||||
let tasks = serializer_cache
|
||||
.values()
|
||||
.map(async |serializer| serializer.can_remove());
|
||||
.map(|serializer| serializer.can_remove());
|
||||
|
||||
// We need to wait to ensure that all the locks are acquired
|
||||
// so there is no **operation** ongoing
|
||||
let _ = join_all(tasks).await;
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
use std::error;
|
||||
use std::{error, pin::Pin};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use pumpkin_util::math::vector2::Vector2;
|
||||
|
||||
@ -39,6 +38,8 @@ pub trait Dirtiable {
|
||||
fn mark_dirty(&mut self, flag: bool);
|
||||
}
|
||||
|
||||
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
|
||||
/// Trait to handle the IO of chunks
|
||||
/// for loading and saving chunks data
|
||||
/// can be implemented for different types of IO
|
||||
@ -46,7 +47,6 @@ pub trait Dirtiable {
|
||||
///
|
||||
/// The `R` type is the type of the data that will be loaded/saved
|
||||
/// like ChunkData or EntityData
|
||||
#[async_trait]
|
||||
pub trait FileIO
|
||||
where
|
||||
Self: Send + Sync,
|
||||
@ -54,40 +54,47 @@ where
|
||||
type Data: Send + Sync + Sized;
|
||||
|
||||
/// Load the chunks data
|
||||
async fn fetch_chunks(
|
||||
&self,
|
||||
folder: &LevelFolder,
|
||||
chunk_coords: &[Vector2<i32>],
|
||||
fn fetch_chunks<'a>(
|
||||
&'a self,
|
||||
folder: &'a LevelFolder,
|
||||
chunk_coords: &'a [Vector2<i32>],
|
||||
stream: tokio::sync::mpsc::Sender<LoadedData<Self::Data, ChunkReadingError>>,
|
||||
);
|
||||
) -> BoxFuture<'a, ()>; // Returns BoxFuture<()>
|
||||
|
||||
/// Persist the chunks data
|
||||
async fn save_chunks(
|
||||
&self,
|
||||
folder: &LevelFolder,
|
||||
fn save_chunks<'a>(
|
||||
&'a self,
|
||||
folder: &'a LevelFolder,
|
||||
chunks_data: Vec<(Vector2<i32>, Self::Data)>,
|
||||
) -> Result<(), ChunkWritingError>;
|
||||
) -> BoxFuture<'a, Result<(), ChunkWritingError>>; // Returns BoxFuture<Result>
|
||||
|
||||
/// Tells the `ChunkIO` that these chunks are currently loaded in memory
|
||||
async fn watch_chunks(&self, folder: &LevelFolder, chunks: &[Vector2<i32>]);
|
||||
fn watch_chunks<'a>(
|
||||
&'a self,
|
||||
folder: &'a LevelFolder,
|
||||
chunks: &'a [Vector2<i32>],
|
||||
) -> BoxFuture<'a, ()>;
|
||||
|
||||
/// Tells the `ChunkIO` that these chunks are no longer loaded in memory
|
||||
async fn unwatch_chunks(&self, folder: &LevelFolder, chunks: &[Vector2<i32>]);
|
||||
fn unwatch_chunks<'a>(
|
||||
&'a self,
|
||||
folder: &'a LevelFolder,
|
||||
chunks: &'a [Vector2<i32>],
|
||||
) -> BoxFuture<'a, ()>;
|
||||
|
||||
/// Tells the `ChunkIO` that no more chunks are loaded in memory
|
||||
async fn clear_watched_chunks(&self);
|
||||
fn clear_watched_chunks(&self) -> BoxFuture<'_, ()>;
|
||||
|
||||
async fn clean_up_log(&self);
|
||||
fn clean_up_log(&self) -> BoxFuture<'_, ()>;
|
||||
|
||||
/// Ensure that all ongoing operations are finished
|
||||
async fn block_and_await_ongoing_tasks(&self);
|
||||
fn block_and_await_ongoing_tasks(&self) -> BoxFuture<'_, ()>;
|
||||
}
|
||||
|
||||
/// Trait to serialize and deserialize the chunk data to and from bytes.
|
||||
///
|
||||
/// The `Data` type is the type of the data that will be updated or serialized/deserialized
|
||||
/// like ChunkData or EntityData
|
||||
#[async_trait]
|
||||
pub trait ChunkSerializer: Send + Sync + Default {
|
||||
type Data: Send + Sync + Sized + Dirtiable;
|
||||
type WriteBackend;
|
||||
@ -98,18 +105,24 @@ pub trait ChunkSerializer: Send + Sync + Default {
|
||||
fn should_write(&self, is_watched: bool) -> bool;
|
||||
|
||||
/// Serialize the data to bytes.
|
||||
async fn write(&self, backend: Self::WriteBackend) -> Result<(), std::io::Error>;
|
||||
fn write(
|
||||
&self,
|
||||
backend: Self::WriteBackend,
|
||||
) -> impl Future<Output = Result<(), std::io::Error>> + Send;
|
||||
|
||||
/// Create a new instance from bytes
|
||||
fn read(r: Bytes) -> Result<Self, ChunkReadingError>;
|
||||
|
||||
/// Add the chunk data to the serializer
|
||||
async fn update_chunk(&mut self, chunk_data: &Self::Data) -> Result<(), ChunkWritingError>;
|
||||
fn update_chunk(
|
||||
&mut self,
|
||||
chunk_data: &Self::Data,
|
||||
) -> impl Future<Output = Result<(), ChunkWritingError>> + Send;
|
||||
|
||||
/// Get the chunks data from the serializer
|
||||
async fn get_chunks(
|
||||
fn get_chunks(
|
||||
&self,
|
||||
chunks: &[Vector2<i32>],
|
||||
stream: tokio::sync::mpsc::Sender<LoadedData<Self::Data, ChunkReadingError>>,
|
||||
);
|
||||
) -> impl Future<Output = ()> + Send;
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use crate::item::ItemStack;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_nbt::{compound::NbtCompound, tag::NbtTag};
|
||||
use std::any::Any;
|
||||
@ -11,34 +10,86 @@ use std::{
|
||||
};
|
||||
use tokio::sync::{Mutex, OwnedMutexGuard};
|
||||
|
||||
// Inventory.java
|
||||
#[async_trait]
|
||||
pub type InventoryFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
|
||||
pub trait Inventory: Send + Sync + Debug + Clearable {
|
||||
fn size(&self) -> usize;
|
||||
|
||||
async fn is_empty(&self) -> bool;
|
||||
// --- Asynchronous Methods (Using BlockFuture) ---
|
||||
|
||||
async fn get_stack(&self, slot: usize) -> Arc<Mutex<ItemStack>>;
|
||||
fn is_empty(&self) -> InventoryFuture<'_, bool>;
|
||||
|
||||
async fn remove_stack(&self, slot: usize) -> ItemStack;
|
||||
fn get_stack(&self, slot: usize) -> InventoryFuture<'_, Arc<Mutex<ItemStack>>>;
|
||||
|
||||
async fn remove_stack_specific(&self, slot: usize, amount: u8) -> ItemStack;
|
||||
fn remove_stack(&self, slot: usize) -> InventoryFuture<'_, ItemStack>;
|
||||
|
||||
fn get_max_count_per_stack(&self) -> u8 {
|
||||
99
|
||||
fn remove_stack_specific(&self, slot: usize, amount: u8) -> InventoryFuture<'_, ItemStack>;
|
||||
|
||||
fn set_stack(&self, slot: usize, stack: ItemStack) -> InventoryFuture<'_, ()>;
|
||||
|
||||
fn on_open(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
fn on_close(&self) -> InventoryFuture<'_, ()> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
|
||||
async fn set_stack(&self, slot: usize, stack: ItemStack);
|
||||
fn count<'a>(&'a self, item: &'a Item) -> InventoryFuture<'a, u8> {
|
||||
Box::pin(async move {
|
||||
let mut count = 0;
|
||||
|
||||
fn mark_dirty(&self) {}
|
||||
for i in 0..self.size() {
|
||||
let slot = self.get_stack(i).await;
|
||||
let stack = slot.lock().await;
|
||||
if stack.get_item().id == item.id {
|
||||
count += stack.item_count;
|
||||
}
|
||||
}
|
||||
|
||||
async fn write_data(
|
||||
count
|
||||
})
|
||||
}
|
||||
|
||||
fn contains_any_predicate<'a>(
|
||||
&'a self,
|
||||
predicate: &'a (dyn Fn(OwnedMutexGuard<ItemStack>) -> bool + Sync),
|
||||
) -> InventoryFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
for i in 0..self.size() {
|
||||
let slot = self.get_stack(i).await;
|
||||
let stack = slot.lock_owned().await;
|
||||
if predicate(stack) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
fn contains_any<'a>(&'a self, items: &'a [Item]) -> InventoryFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
self.contains_any_predicate(&|stack| {
|
||||
!stack.is_empty() && items.contains(stack.get_item())
|
||||
})
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
||||
// --- Default Implementation: write_data (Using BlockFuture) ---
|
||||
fn write_data(
|
||||
&self,
|
||||
nbt: &mut pumpkin_nbt::compound::NbtCompound,
|
||||
nbt: &mut NbtCompound,
|
||||
stacks: &[Arc<Mutex<ItemStack>>],
|
||||
include_empty: bool,
|
||||
) {
|
||||
) -> InventoryFuture<'_, ()> {
|
||||
// Clone for the move block (requires `nbt` and `stacks` to be cloneable/to_owned)
|
||||
let nbt = nbt.to_owned();
|
||||
let stacks = stacks.to_owned();
|
||||
|
||||
Box::pin(async move {
|
||||
let mut slots = Vec::new();
|
||||
let mut nbt = nbt;
|
||||
|
||||
for (i, item) in stacks.iter().enumerate() {
|
||||
let stack = item.lock().await;
|
||||
@ -55,13 +106,18 @@ pub trait Inventory: Send + Sync + Debug + Clearable {
|
||||
}
|
||||
|
||||
nbt.put("Items", NbtTag::List(slots));
|
||||
})
|
||||
}
|
||||
|
||||
fn read_data(
|
||||
&self,
|
||||
nbt: &pumpkin_nbt::compound::NbtCompound,
|
||||
stacks: &[Arc<Mutex<ItemStack>>],
|
||||
) {
|
||||
// --- Synchronous Methods (No Change) ---
|
||||
|
||||
fn get_max_count_per_stack(&self) -> u8 {
|
||||
99
|
||||
}
|
||||
|
||||
fn mark_dirty(&self) {}
|
||||
|
||||
fn read_data(&self, nbt: &NbtCompound, stacks: &[Arc<Mutex<ItemStack>>]) {
|
||||
if let Some(inventory_list) = nbt.get_list("Items") {
|
||||
for tag in inventory_list {
|
||||
if let Some(item_compound) = tag.extract_compound()
|
||||
@ -71,7 +127,6 @@ pub trait Inventory: Send + Sync + Debug + Clearable {
|
||||
if slot < stacks.len()
|
||||
&& let Some(item_stack) = ItemStack::read_item_stack(item_compound)
|
||||
{
|
||||
// This won't error cause it's only called on initialization
|
||||
*stacks[slot].try_lock().unwrap() = item_stack;
|
||||
}
|
||||
}
|
||||
@ -79,15 +134,6 @@ pub trait Inventory: Send + Sync + Debug + Clearable {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
boolean canPlayerUse(PlayerEntity player);
|
||||
*/
|
||||
|
||||
// TODO: Add (PlayerEntity player)
|
||||
async fn on_open(&self) {}
|
||||
async fn on_close(&self) {}
|
||||
|
||||
/// isValid is source
|
||||
fn is_valid_slot_for(&self, _slot: usize, _stack: &ItemStack) -> bool {
|
||||
true
|
||||
}
|
||||
@ -101,42 +147,6 @@ pub trait Inventory: Send + Sync + Debug + Clearable {
|
||||
true
|
||||
}
|
||||
|
||||
async fn count(&self, item: &Item) -> u8 {
|
||||
let mut count = 0;
|
||||
|
||||
for i in 0..self.size() {
|
||||
let slot = self.get_stack(i).await;
|
||||
let stack = slot.lock().await;
|
||||
if stack.get_item().id == item.id {
|
||||
count += stack.item_count;
|
||||
}
|
||||
}
|
||||
|
||||
count
|
||||
}
|
||||
|
||||
async fn contains_any_predicate(
|
||||
&self,
|
||||
predicate: &(dyn Fn(OwnedMutexGuard<ItemStack>) -> bool + Sync),
|
||||
) -> bool {
|
||||
for i in 0..self.size() {
|
||||
let slot = self.get_stack(i).await;
|
||||
let stack = slot.lock_owned().await;
|
||||
if predicate(stack) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
async fn contains_any(&self, items: &[Item]) -> bool {
|
||||
self.contains_any_predicate(&|stack| !stack.is_empty() && items.contains(stack.get_item()))
|
||||
.await
|
||||
}
|
||||
|
||||
// TODO: canPlayerUse
|
||||
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,6 @@ tokio = { workspace = true, features = [
|
||||
] }
|
||||
rayon.workspace = true
|
||||
thiserror.workspace = true
|
||||
async-trait.workspace = true
|
||||
futures.workspace = true
|
||||
|
||||
# config
|
||||
|
||||
@ -5,11 +5,13 @@ use crate::block::{
|
||||
registry::BlockActionResult,
|
||||
{BlockBehaviour, NormalUseArgs},
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
|
||||
use pumpkin_data::block_properties::{BarrelLikeProperties, BlockProperties};
|
||||
use pumpkin_inventory::generic_container_screen_handler::create_generic_9x3;
|
||||
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
||||
use pumpkin_inventory::screen_handler::{InventoryPlayer, ScreenHandler, ScreenHandlerFactory};
|
||||
use pumpkin_inventory::screen_handler::{
|
||||
BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
|
||||
};
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use pumpkin_world::BlockStateId;
|
||||
@ -19,17 +21,19 @@ use tokio::sync::Mutex;
|
||||
|
||||
struct BarrelScreenFactory(Arc<dyn Inventory>);
|
||||
|
||||
#[async_trait]
|
||||
impl ScreenHandlerFactory for BarrelScreenFactory {
|
||||
async fn create_screen_handler(
|
||||
&self,
|
||||
fn create_screen_handler<'a>(
|
||||
&'a self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
) -> Option<Arc<Mutex<dyn ScreenHandler>>> {
|
||||
Some(Arc::new(Mutex::new(
|
||||
create_generic_9x3(sync_id, player_inventory, self.0.clone()).await,
|
||||
)))
|
||||
player_inventory: &'a Arc<PlayerInventory>,
|
||||
_player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, Option<SharedScreenHandler>> {
|
||||
Box::pin(async move {
|
||||
let handler = create_generic_9x3(sync_id, player_inventory, self.0.clone()).await;
|
||||
let concrete_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(concrete_arc as SharedScreenHandler)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_display_name(&self) -> TextComponent {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use futures::future::join;
|
||||
use pumpkin_data::block_properties::{
|
||||
BlockProperties, ChestLikeProperties, ChestType, HorizontalFacing,
|
||||
@ -11,7 +10,9 @@ use pumpkin_data::{Block, BlockDirection};
|
||||
use pumpkin_inventory::double::DoubleInventory;
|
||||
use pumpkin_inventory::generic_container_screen_handler::{create_generic_9x3, create_generic_9x6};
|
||||
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
||||
use pumpkin_inventory::screen_handler::{InventoryPlayer, ScreenHandler, ScreenHandlerFactory};
|
||||
use pumpkin_inventory::screen_handler::{
|
||||
BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
|
||||
};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use pumpkin_world::BlockStateId;
|
||||
@ -34,19 +35,24 @@ use crate::{
|
||||
|
||||
struct ChestScreenFactory(Arc<dyn Inventory>);
|
||||
|
||||
#[async_trait]
|
||||
impl ScreenHandlerFactory for ChestScreenFactory {
|
||||
async fn create_screen_handler(
|
||||
&self,
|
||||
fn create_screen_handler<'a>(
|
||||
&'a self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
) -> Option<Arc<Mutex<dyn ScreenHandler>>> {
|
||||
Some(Arc::new(Mutex::new(if self.0.size() > 27 {
|
||||
player_inventory: &'a Arc<PlayerInventory>,
|
||||
_player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, Option<SharedScreenHandler>> {
|
||||
Box::pin(async move {
|
||||
let concrete_handler = if self.0.size() > 27 {
|
||||
create_generic_9x6(sync_id, player_inventory, self.0.clone()).await
|
||||
} else {
|
||||
create_generic_9x3(sync_id, player_inventory, self.0.clone()).await
|
||||
})))
|
||||
};
|
||||
|
||||
let concrete_arc = Arc::new(Mutex::new(concrete_handler));
|
||||
|
||||
Some(concrete_arc as SharedScreenHandler)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_display_name(&self) -> TextComponent {
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{BlockBehaviour, BlockFuture, NormalUseArgs};
|
||||
use async_trait::async_trait;
|
||||
|
||||
use pumpkin_inventory::crafting::crafting_screen_handler::CraftingTableScreenHandler;
|
||||
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
||||
use pumpkin_inventory::screen_handler::{InventoryPlayer, ScreenHandler, ScreenHandlerFactory};
|
||||
use pumpkin_inventory::screen_handler::{
|
||||
BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
|
||||
};
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use std::sync::Arc;
|
||||
@ -26,17 +28,19 @@ impl BlockBehaviour for CraftingTableBlock {
|
||||
|
||||
struct CraftingTableScreenFactory;
|
||||
|
||||
#[async_trait]
|
||||
impl ScreenHandlerFactory for CraftingTableScreenFactory {
|
||||
async fn create_screen_handler(
|
||||
&self,
|
||||
fn create_screen_handler<'a>(
|
||||
&'a self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
) -> Option<Arc<Mutex<dyn ScreenHandler>>> {
|
||||
Some(Arc::new(Mutex::new(
|
||||
CraftingTableScreenHandler::new(sync_id, player_inventory).await,
|
||||
)))
|
||||
player_inventory: &'a Arc<PlayerInventory>,
|
||||
_player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, Option<SharedScreenHandler>> {
|
||||
Box::pin(async move {
|
||||
let handler = CraftingTableScreenHandler::new(sync_id, player_inventory).await;
|
||||
let concrete_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(concrete_arc as SharedScreenHandler)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_display_name(&self) -> TextComponent {
|
||||
|
||||
@ -4,12 +4,11 @@ use crate::block::{
|
||||
BlockBehaviour, BlockFuture, NormalUseArgs, OnPlaceArgs, OnSyncedBlockEventArgs, PlacedArgs,
|
||||
registry::BlockActionResult,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::block_properties::{BlockProperties, LadderLikeProperties};
|
||||
use pumpkin_inventory::{
|
||||
generic_container_screen_handler::create_generic_9x3,
|
||||
player::player_inventory::PlayerInventory,
|
||||
screen_handler::{InventoryPlayer, ScreenHandler, ScreenHandlerFactory},
|
||||
screen_handler::{BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler},
|
||||
};
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
@ -20,17 +19,19 @@ use tokio::sync::Mutex;
|
||||
|
||||
struct EnderChestScreenFactory(Arc<dyn Inventory>);
|
||||
|
||||
#[async_trait]
|
||||
impl ScreenHandlerFactory for EnderChestScreenFactory {
|
||||
async fn create_screen_handler(
|
||||
&self,
|
||||
fn create_screen_handler<'a>(
|
||||
&'a self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
) -> Option<Arc<Mutex<dyn ScreenHandler>>> {
|
||||
Some(Arc::new(Mutex::new(
|
||||
create_generic_9x3(sync_id, player_inventory, self.0.clone()).await,
|
||||
)))
|
||||
player_inventory: &'a Arc<PlayerInventory>,
|
||||
_player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, Option<SharedScreenHandler>> {
|
||||
Box::pin(async move {
|
||||
let handler = create_generic_9x3(sync_id, player_inventory, self.0.clone()).await;
|
||||
let concrete_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(concrete_arc as SharedScreenHandler)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_display_name(&self) -> TextComponent {
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::block_properties::{BlockProperties, FurnaceLikeProperties};
|
||||
use pumpkin_inventory::{
|
||||
furnace::furnace_screen_handler::FurnaceScreenHandler, screen_handler::ScreenHandlerFactory,
|
||||
furnace::furnace_screen_handler::FurnaceScreenHandler,
|
||||
player::player_inventory::PlayerInventory,
|
||||
screen_handler::{BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler},
|
||||
};
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
@ -33,22 +34,26 @@ impl FurnaceScreenFactory {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ScreenHandlerFactory for FurnaceScreenFactory {
|
||||
async fn create_screen_handler(
|
||||
&self,
|
||||
fn create_screen_handler<'a>(
|
||||
&'a self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<pumpkin_inventory::player::player_inventory::PlayerInventory>,
|
||||
_player: &dyn pumpkin_inventory::screen_handler::InventoryPlayer,
|
||||
) -> Option<Arc<Mutex<dyn pumpkin_inventory::screen_handler::ScreenHandler>>> {
|
||||
let furnace_screen_handler = FurnaceScreenHandler::new(
|
||||
player_inventory: &'a Arc<PlayerInventory>,
|
||||
_player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, Option<SharedScreenHandler>> {
|
||||
Box::pin(async move {
|
||||
let concrete_handler = FurnaceScreenHandler::new(
|
||||
sync_id,
|
||||
player_inventory,
|
||||
self.inventory.clone(),
|
||||
self.block_entity.clone(),
|
||||
)
|
||||
.await;
|
||||
Some(Arc::new(Mutex::new(furnace_screen_handler)))
|
||||
|
||||
let concrete_arc = Arc::new(Mutex::new(concrete_handler));
|
||||
|
||||
Some(concrete_arc as SharedScreenHandler)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_display_name(&self) -> pumpkin_util::text::TextComponent {
|
||||
|
||||
@ -7,12 +7,14 @@ use crate::block::{
|
||||
{BlockBehaviour, NormalUseArgs},
|
||||
};
|
||||
use crate::world::World;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use pumpkin_data::block_properties::{BlockProperties, HopperFacing};
|
||||
use pumpkin_data::{Block, BlockDirection};
|
||||
use pumpkin_inventory::generic_container_screen_handler::create_hopper;
|
||||
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
||||
use pumpkin_inventory::screen_handler::{InventoryPlayer, ScreenHandler, ScreenHandlerFactory};
|
||||
use pumpkin_inventory::screen_handler::{
|
||||
BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
|
||||
};
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
@ -24,17 +26,20 @@ use tokio::sync::Mutex;
|
||||
|
||||
struct HopperBlockScreenFactory(Arc<dyn Inventory>);
|
||||
|
||||
#[async_trait]
|
||||
impl ScreenHandlerFactory for HopperBlockScreenFactory {
|
||||
async fn create_screen_handler(
|
||||
&self,
|
||||
fn create_screen_handler<'a>(
|
||||
&'a self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
) -> Option<Arc<Mutex<dyn ScreenHandler>>> {
|
||||
Some(Arc::new(Mutex::new(
|
||||
create_hopper(sync_id, player_inventory, self.0.clone()).await,
|
||||
)))
|
||||
player_inventory: &'a Arc<PlayerInventory>,
|
||||
_player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, Option<SharedScreenHandler>> {
|
||||
Box::pin(async move {
|
||||
let concrete_handler = create_hopper(sync_id, player_inventory, self.0.clone()).await;
|
||||
|
||||
let concrete_arc = Arc::new(Mutex::new(concrete_handler));
|
||||
|
||||
Some(concrete_arc as SharedScreenHandler)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_display_name(&self) -> TextComponent {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::block_properties::{BlockProperties, HorizontalFacing, Integer1To4};
|
||||
use pumpkin_world::BlockStateId;
|
||||
|
||||
use crate::block::{BlockBehaviour, CanUpdateAtArgs};
|
||||
use crate::block::{BlockBehaviour, BlockFuture, CanUpdateAtArgs};
|
||||
use crate::block::{BlockIsReplacing, OnPlaceArgs};
|
||||
|
||||
pub trait SegmentProperties {
|
||||
@ -43,7 +42,6 @@ impl_segment_properties!(
|
||||
segment_amount
|
||||
);
|
||||
|
||||
#[async_trait]
|
||||
pub trait Segmented: BlockBehaviour {
|
||||
type Properties: BlockProperties + SegmentProperties;
|
||||
|
||||
@ -80,30 +78,34 @@ pub trait Segmented: BlockBehaviour {
|
||||
}
|
||||
}
|
||||
|
||||
async fn can_update_at(&self, ctx: CanUpdateAtArgs<'_>) -> bool {
|
||||
fn can_update_at<'a>(&'a self, ctx: CanUpdateAtArgs<'a>) -> BlockFuture<'a, bool> {
|
||||
Box::pin(async move {
|
||||
let current_props = Self::Properties::from_state_id(ctx.state_id, ctx.block);
|
||||
self.can_add_segment(¤t_props)
|
||||
})
|
||||
}
|
||||
|
||||
async fn on_place(&self, ctx: OnPlaceArgs<'_>) -> BlockStateId {
|
||||
if let BlockIsReplacing::Itself(existing_state_id) = ctx.replacing {
|
||||
let mut props = Self::Properties::from_state_id(existing_state_id, ctx.block);
|
||||
fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
|
||||
Box::pin(async move {
|
||||
if let BlockIsReplacing::Itself(existing_state_id) = args.replacing {
|
||||
let mut props = Self::Properties::from_state_id(existing_state_id, args.block);
|
||||
|
||||
if self.can_add_segment(&props) {
|
||||
let current_amount = props.get_segment_amount();
|
||||
let next_amount = self.get_next_segment_amount(current_amount);
|
||||
props.set_segment_amount(next_amount);
|
||||
props.to_state_id(ctx.block)
|
||||
props.to_state_id(args.block)
|
||||
} else {
|
||||
existing_state_id
|
||||
}
|
||||
} else {
|
||||
// Set first segment orientation based on player direction
|
||||
let player_facing = ctx.player.living_entity.entity.get_horizontal_facing();
|
||||
let mut props = Self::Properties::default(ctx.block);
|
||||
let player_facing = args.player.living_entity.entity.get_horizontal_facing();
|
||||
let mut props = Self::Properties::default(args.block);
|
||||
props.set_segment_amount(Integer1To4::L1);
|
||||
props.set_facing(self.get_facing_for_segment(player_facing, Integer1To4::L1));
|
||||
props.to_state_id(ctx.block)
|
||||
props.to_state_id(args.block)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,14 +6,16 @@ use crate::block::{
|
||||
};
|
||||
use crate::entity::Entity;
|
||||
use crate::entity::item::ItemEntity;
|
||||
use async_trait::async_trait;
|
||||
|
||||
use pumpkin_data::FacingExt;
|
||||
use pumpkin_data::block_properties::{BlockProperties, Facing};
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_data::world::WorldEvent;
|
||||
use pumpkin_inventory::generic_container_screen_handler::create_generic_3x3;
|
||||
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
||||
use pumpkin_inventory::screen_handler::{InventoryPlayer, ScreenHandler, ScreenHandlerFactory};
|
||||
use pumpkin_inventory::screen_handler::{
|
||||
BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
|
||||
};
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
@ -30,17 +32,19 @@ use uuid::Uuid;
|
||||
|
||||
struct DropperScreenFactory(Arc<dyn Inventory>);
|
||||
|
||||
#[async_trait]
|
||||
impl ScreenHandlerFactory for DropperScreenFactory {
|
||||
async fn create_screen_handler(
|
||||
&self,
|
||||
fn create_screen_handler<'a>(
|
||||
&'a self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
) -> Option<Arc<Mutex<dyn ScreenHandler>>> {
|
||||
Some(Arc::new(Mutex::new(
|
||||
create_generic_3x3(sync_id, player_inventory, self.0.clone()).await,
|
||||
)))
|
||||
player_inventory: &'a Arc<PlayerInventory>,
|
||||
_player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, Option<SharedScreenHandler>> {
|
||||
Box::pin(async move {
|
||||
let handler = create_generic_3x3(sync_id, player_inventory, self.0.clone()).await;
|
||||
let screen_handler_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(screen_handler_arc as SharedScreenHandler)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_display_name(&self) -> TextComponent {
|
||||
|
||||
@ -5,12 +5,14 @@ use crate::block::{
|
||||
registry::BlockActionResult,
|
||||
{BlockBehaviour, NormalUseArgs},
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
|
||||
use pumpkin_data::block_properties::BlockProperties;
|
||||
use pumpkin_data::tag::{RegistryKey, get_tag_values};
|
||||
use pumpkin_inventory::generic_container_screen_handler::create_generic_9x3;
|
||||
use pumpkin_inventory::player::player_inventory::PlayerInventory;
|
||||
use pumpkin_inventory::screen_handler::{InventoryPlayer, ScreenHandler, ScreenHandlerFactory};
|
||||
use pumpkin_inventory::screen_handler::{
|
||||
BoxFuture, InventoryPlayer, ScreenHandlerFactory, SharedScreenHandler,
|
||||
};
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use pumpkin_world::BlockStateId;
|
||||
use pumpkin_world::block::entities::shulker_box::ShulkerBoxBlockEntity;
|
||||
@ -19,17 +21,19 @@ use tokio::sync::Mutex;
|
||||
|
||||
struct ShulkerBoxScreenFactory(Arc<dyn Inventory>);
|
||||
|
||||
#[async_trait]
|
||||
impl ScreenHandlerFactory for ShulkerBoxScreenFactory {
|
||||
async fn create_screen_handler(
|
||||
&self,
|
||||
fn create_screen_handler<'a>(
|
||||
&'a self,
|
||||
sync_id: u8,
|
||||
player_inventory: &Arc<PlayerInventory>,
|
||||
_player: &dyn InventoryPlayer,
|
||||
) -> Option<Arc<Mutex<dyn ScreenHandler>>> {
|
||||
Some(Arc::new(Mutex::new(
|
||||
create_generic_9x3(sync_id, player_inventory, self.0.clone()).await,
|
||||
)))
|
||||
player_inventory: &'a Arc<PlayerInventory>,
|
||||
_player: &'a dyn InventoryPlayer,
|
||||
) -> BoxFuture<'a, Option<SharedScreenHandler>> {
|
||||
Box::pin(async move {
|
||||
let handler = create_generic_9x3(sync_id, player_inventory, self.0.clone()).await;
|
||||
let screen_handler_arc = Arc::new(Mutex::new(handler));
|
||||
|
||||
Some(screen_handler_arc as SharedScreenHandler)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_display_name(&self) -> TextComponent {
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
pub mod context;
|
||||
pub mod events;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::{pin::Pin, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
pub use context::*;
|
||||
pub use events::*;
|
||||
|
||||
@ -24,12 +23,12 @@ pub struct PluginMetadata<'s> {
|
||||
pub description: &'s str,
|
||||
}
|
||||
|
||||
type PluginFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
|
||||
/// Trait representing a plugin with asynchronous lifecycle methods.
|
||||
///
|
||||
/// This trait defines the required methods for a plugin, including hooks for when
|
||||
/// the plugin is loaded and unloaded. It is marked with `async_trait` to allow
|
||||
/// for asynchronous implementations.
|
||||
#[async_trait]
|
||||
/// the plugin is loaded and unloaded.
|
||||
pub trait Plugin: Send + Sync + 'static {
|
||||
/// Asynchronous method called when the plugin is loaded.
|
||||
///
|
||||
@ -40,8 +39,8 @@ pub trait Plugin: Send + Sync + 'static {
|
||||
///
|
||||
/// # Returns
|
||||
/// - `Ok(())` on success, or `Err(String)` on failure.
|
||||
async fn on_load(&mut self, _server: Arc<Context>) -> Result<(), String> {
|
||||
Ok(())
|
||||
fn on_load(&mut self, _server: Arc<Context>) -> PluginFuture<'_, Result<(), String>> {
|
||||
Box::pin(async move { Ok(()) })
|
||||
}
|
||||
|
||||
/// Asynchronous method called when the plugin is unloaded.
|
||||
@ -53,7 +52,7 @@ pub trait Plugin: Send + Sync + 'static {
|
||||
///
|
||||
/// # Returns
|
||||
/// - `Ok(())` on success, or `Err(String)` on failure.
|
||||
async fn on_unload(&mut self, _server: Arc<Context>) -> Result<(), String> {
|
||||
Ok(())
|
||||
fn on_unload(&mut self, _server: Arc<Context>) -> PluginFuture<'_, Result<(), String>> {
|
||||
Box::pin(async move { Ok(()) })
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
use async_trait::async_trait;
|
||||
use futures::future::join_all;
|
||||
use loader::{LoaderError, PluginLoader, native::NativePluginLoader};
|
||||
use std::{
|
||||
any::Any,
|
||||
collections::{HashMap, HashSet},
|
||||
path::{Path, PathBuf},
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
};
|
||||
use thiserror::Error;
|
||||
@ -16,26 +16,31 @@ pub mod loader;
|
||||
use crate::{PERMISSION_MANAGER, server::Server};
|
||||
pub use api::*;
|
||||
|
||||
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
|
||||
/// A trait for handling events dynamically.
|
||||
///
|
||||
/// This trait allows for handling events of any type that implements the `Event` trait.
|
||||
#[async_trait]
|
||||
pub trait DynEventHandler: Send + Sync {
|
||||
/// Asynchronously handles a dynamic event.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `event`: A reference to the event to handle.
|
||||
async fn handle_dyn(&self, _server: &Arc<Server>, event: &(dyn Payload + Send + Sync));
|
||||
fn handle_dyn<'a>(
|
||||
&'a self,
|
||||
_server: &'a Arc<Server>,
|
||||
event: &'a (dyn Payload + Send + Sync),
|
||||
) -> BoxFuture<'a, ()>;
|
||||
|
||||
/// Asynchronously handles a blocking dynamic event.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `event`: A mutable reference to the event to handle.
|
||||
async fn handle_blocking_dyn(
|
||||
&self,
|
||||
_server: &Arc<Server>,
|
||||
_event: &mut (dyn Payload + Send + Sync),
|
||||
);
|
||||
fn handle_blocking_dyn<'a>(
|
||||
&'a self,
|
||||
_server: &'a Arc<Server>,
|
||||
_event: &'a mut (dyn Payload + Send + Sync),
|
||||
) -> BoxFuture<'a, ()>;
|
||||
|
||||
/// Checks if the event handler is blocking.
|
||||
///
|
||||
@ -53,19 +58,22 @@ pub trait DynEventHandler: Send + Sync {
|
||||
/// A trait for handling specific events.
|
||||
///
|
||||
/// This trait allows for handling events of a specific type that implements the `Event` trait.
|
||||
#[async_trait]
|
||||
pub trait EventHandler<E: Payload>: Send + Sync {
|
||||
/// Asynchronously handles an event of type `E`.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `event`: A reference to the event to handle.
|
||||
async fn handle(&self, _server: &Arc<Server>, _event: &E) {}
|
||||
fn handle(&self, _server: &Arc<Server>, _event: &E) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
|
||||
/// Asynchronously handles a blocking event of type `E`.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `event`: A mutable reference to the event to handle.
|
||||
async fn handle_blocking(&self, _server: &Arc<Server>, _event: &mut E) {}
|
||||
fn handle_blocking(&self, _server: &Arc<Server>, _event: &mut E) -> BoxFuture<'_, ()> {
|
||||
Box::pin(async move {})
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct representing a typed event handler.
|
||||
@ -82,28 +90,37 @@ where
|
||||
_phantom: std::marker::PhantomData<E>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<E, H> DynEventHandler for TypedEventHandler<E, H>
|
||||
where
|
||||
E: Payload + Send + Sync + 'static,
|
||||
H: EventHandler<E> + Send + Sync,
|
||||
{
|
||||
/// Asynchronously handles a blocking dynamic event.
|
||||
async fn handle_blocking_dyn(
|
||||
&self,
|
||||
server: &Arc<Server>,
|
||||
event: &mut (dyn Payload + Send + Sync),
|
||||
) {
|
||||
fn handle_blocking_dyn<'a>(
|
||||
&'a self,
|
||||
server: &'a Arc<Server>,
|
||||
event: &'a mut (dyn Payload + Send + Sync),
|
||||
) -> BoxFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
if let Some(typed_event) = <dyn Payload>::downcast_mut(event) {
|
||||
// The handler.handle_blocking call now returns a Future, which we await.
|
||||
self.handler.handle_blocking(server, typed_event).await;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Asynchronously handles a dynamic event.
|
||||
async fn handle_dyn(&self, server: &Arc<Server>, event: &(dyn Payload + Send + Sync)) {
|
||||
fn handle_dyn<'a>(
|
||||
&'a self,
|
||||
server: &'a Arc<Server>,
|
||||
event: &'a (dyn Payload + Send + Sync),
|
||||
) -> BoxFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
if let Some(typed_event) = <dyn Payload>::downcast_ref(event) {
|
||||
// The handler.handle call now returns a Future, which we await.
|
||||
self.handler.handle(server, typed_event).await;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Checks if the handler is blocking.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user