|
@ -960,6 +960,125 @@ impl ItemManager { |
|
|
Ok(weapon)
|
|
|
Ok(weapon)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub async fn trade_items<EG: EntityGateway>(&mut self,
|
|
|
|
|
|
entity_gateway: &mut EG,
|
|
|
|
|
|
p1: (&AreaClient, &CharacterEntity, &Vec<TradeItem>),
|
|
|
|
|
|
p2: (&AreaClient, &CharacterEntity, &Vec<TradeItem>))
|
|
|
|
|
|
-> Result<Vec<ItemToTrade>, anyhow::Error> {
|
|
|
|
|
|
let it = ItemTransaction::new(&self, (p1, p2))
|
|
|
|
|
|
.act(|it, (p1, p2)| -> Result<_, anyhow::Error> {
|
|
|
|
|
|
let p1_inventory = it.manager.get_character_inventory(p1.1)?;
|
|
|
|
|
|
let p2_inventory = it.manager.get_character_inventory(p2.1)?;
|
|
|
|
|
|
|
|
|
|
|
|
//TODO: inv-selftrade+othertrade <= 30
|
|
|
|
|
|
//if p1_inventory
|
|
|
|
|
|
|
|
|
|
|
|
let trade_items = [(p1, p2, p1_inventory), (p2, p1, p2_inventory)]
|
|
|
|
|
|
.map(|((src_client, dest_client, src_inventory))| {
|
|
|
|
|
|
src_client.2.iter()
|
|
|
|
|
|
.map(|item| -> Option<(Option<ItemToTrade>, Vec<Box<dyn ItemAction<EG>>>)> {
|
|
|
|
|
|
match item {
|
|
|
|
|
|
TradeItem::Individual(item_id) => {
|
|
|
|
|
|
let item = src_inventory.get_item_by_id(*item_id)?.individual()?;
|
|
|
|
|
|
Some((
|
|
|
|
|
|
Some(ItemToTrade {
|
|
|
|
|
|
add_to: *dest_client.0,
|
|
|
|
|
|
remove_from: *src_client.0,
|
|
|
|
|
|
item_id: *item_id,
|
|
|
|
|
|
item_detail: ItemToTradeDetail::Individual(item.item.clone())
|
|
|
|
|
|
}),
|
|
|
|
|
|
vec![
|
|
|
|
|
|
Box::new(AddIndividualItemToInventory {
|
|
|
|
|
|
character_id: dest_client.1.id,
|
|
|
|
|
|
item_id: item.entity_id,
|
|
|
|
|
|
}),
|
|
|
|
|
|
Box::new(RemoveIndividualItemFromInventory {
|
|
|
|
|
|
character_id: src_client.1.id,
|
|
|
|
|
|
item_id: item.entity_id,
|
|
|
|
|
|
})
|
|
|
|
|
|
]
|
|
|
|
|
|
))
|
|
|
|
|
|
},
|
|
|
|
|
|
TradeItem::Stacked(item_id, amount) => {
|
|
|
|
|
|
let item = src_inventory.get_item_by_id(*item_id)?.stacked()?;
|
|
|
|
|
|
if item.count() < *amount {
|
|
|
|
|
|
None
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
Some((
|
|
|
|
|
|
Some(ItemToTrade {
|
|
|
|
|
|
add_to: *dest_client.0,
|
|
|
|
|
|
remove_from: *src_client.0,
|
|
|
|
|
|
item_id: *item_id,
|
|
|
|
|
|
item_detail: ItemToTradeDetail::Stacked(item.tool, *amount)
|
|
|
|
|
|
}),
|
|
|
|
|
|
vec![
|
|
|
|
|
|
Box::new(AddStackedItemToInventory {
|
|
|
|
|
|
character_id: dest_client.1.id,
|
|
|
|
|
|
item_ids: item.entity_ids.iter().cloned().take(*amount).collect(),
|
|
|
|
|
|
}),
|
|
|
|
|
|
Box::new(RemoveStackedItemFromInventory {
|
|
|
|
|
|
character_id: src_client.1.id,
|
|
|
|
|
|
item_ids: item.entity_ids.iter().cloned().take(*amount).collect(),
|
|
|
|
|
|
}),
|
|
|
|
|
|
]
|
|
|
|
|
|
))
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
TradeItem::Meseta(amount) => {
|
|
|
|
|
|
Some((None,
|
|
|
|
|
|
vec![
|
|
|
|
|
|
Box::new(AddMesetaToInventory {
|
|
|
|
|
|
character_id: dest_client.1.id,
|
|
|
|
|
|
amount: *amount,
|
|
|
|
|
|
}),
|
|
|
|
|
|
Box::new(RemoveMesetaFromInventory {
|
|
|
|
|
|
character_id: src_client.1.id,
|
|
|
|
|
|
amount: *amount,
|
|
|
|
|
|
}),
|
|
|
|
|
|
]
|
|
|
|
|
|
))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.collect::<Option<Vec<_>>>()
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if let [Some(p1_trades), Some(p2_trades)] = trade_items {
|
|
|
|
|
|
let (p1_item_trades, p1_item_actions): (Vec<Option<ItemToTrade>>, Vec<Vec<Box<dyn ItemAction<EG>>>>) = p1_trades.into_iter().unzip();
|
|
|
|
|
|
let (p2_item_trades, p2_item_actions): (Vec<Option<ItemToTrade>>, Vec<Vec<Box<dyn ItemAction<EG>>>>) = p2_trades.into_iter().unzip();
|
|
|
|
|
|
let item_trades = p1_item_trades.into_iter().flatten().chain(p2_item_trades.into_iter().flatten());
|
|
|
|
|
|
let item_actions = p1_item_actions.into_iter().flatten().chain(p2_item_actions.into_iter().flatten());
|
|
|
|
|
|
|
|
|
|
|
|
for action in item_actions {
|
|
|
|
|
|
it.action(action);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Ok(item_trades.collect())
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
Err(ItemManagerError::InvalidTrade.into())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
it.commit(self, entity_gateway)
|
|
|
|
|
|
.await
|
|
|
|
|
|
.map_err(|err| err.into())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub enum ItemToTradeDetail {
|
|
|
|
|
|
Individual(ItemDetail),
|
|
|
|
|
|
Stacked(Tool, usize),
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct ItemToTrade {
|
|
|
|
|
|
pub add_to: AreaClient,
|
|
|
|
|
|
pub remove_from: AreaClient,
|
|
|
|
|
|
pub item_id: ClientItemId,
|
|
|
|
|
|
pub item_detail: ItemToTradeDetail,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct RemoveFromLocalFloor {
|
|
|
struct RemoveFromLocalFloor {
|
|
|
character_id: CharacterEntityId,
|
|
|
character_id: CharacterEntityId,
|
|
@ -1050,3 +1169,76 @@ impl<EG: EntityGateway> ItemAction<EG> for AddMesetaFloorItemToInventory { |
|
|
Ok(())
|
|
|
Ok(())
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct AddIndividualItemToInventory {
|
|
|
|
|
|
character_id: CharacterEntityId,
|
|
|
|
|
|
item_id: ItemEntityId,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
|
|
|
|
|
impl<EG: EntityGateway> ItemAction<EG> for AddIndividualItemToInventory {
|
|
|
|
|
|
async fn commit(&self, _item_manager: &mut ItemManager, entity_gateway: &mut EG) -> Result<(), TransactionCommitError> {
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct AddStackedItemToInventory {
|
|
|
|
|
|
character_id: CharacterEntityId,
|
|
|
|
|
|
item_ids: Vec<ItemEntityId>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
|
|
|
|
|
impl<EG: EntityGateway> ItemAction<EG> for AddStackedItemToInventory {
|
|
|
|
|
|
async fn commit(&self, _item_manager: &mut ItemManager, entity_gateway: &mut EG) -> Result<(), TransactionCommitError> {
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct RemoveIndividualItemFromInventory {
|
|
|
|
|
|
character_id: CharacterEntityId,
|
|
|
|
|
|
item_id: ItemEntityId,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
|
|
|
|
|
impl<EG: EntityGateway> ItemAction<EG> for RemoveIndividualItemFromInventory {
|
|
|
|
|
|
async fn commit(&self, _item_manager: &mut ItemManager, entity_gateway: &mut EG) -> Result<(), TransactionCommitError> {
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct RemoveStackedItemFromInventory {
|
|
|
|
|
|
character_id: CharacterEntityId,
|
|
|
|
|
|
item_ids: Vec<ItemEntityId>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
|
|
|
|
|
impl<EG: EntityGateway> ItemAction<EG> for RemoveStackedItemFromInventory {
|
|
|
|
|
|
async fn commit(&self, _item_manager: &mut ItemManager, entity_gateway: &mut EG) -> Result<(), TransactionCommitError> {
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct AddMesetaToInventory {
|
|
|
|
|
|
character_id: CharacterEntityId,
|
|
|
|
|
|
amount: usize,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
|
|
|
|
|
impl<EG: EntityGateway> ItemAction<EG> for AddMesetaToInventory {
|
|
|
|
|
|
async fn commit(&self, _item_manager: &mut ItemManager, entity_gateway: &mut EG) -> Result<(), TransactionCommitError> {
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct RemoveMesetaFromInventory {
|
|
|
|
|
|
character_id: CharacterEntityId,
|
|
|
|
|
|
amount: usize,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
|
|
|
|
|
impl<EG: EntityGateway> ItemAction<EG> for RemoveMesetaFromInventory {
|
|
|
|
|
|
async fn commit(&self, _item_manager: &mut ItemManager, entity_gateway: &mut EG) -> Result<(), TransactionCommitError> {
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|