selling items
This commit is contained in:
parent
eb9fdb485b
commit
6bacdd4fe3
@ -787,3 +787,48 @@ where
|
|||||||
Ok((transaction, result))
|
Ok((transaction, result))
|
||||||
}).await
|
}).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn sell_inventory_item<'a>(character_id: CharacterEntityId)
|
||||||
|
-> impl Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction + 'a>), InventoryItem)
|
||||||
|
-> Pin<Box<dyn Future<Output=Result<((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction + 'a>), InventoryItem), ItemStateError>> + Send + 'a>>
|
||||||
|
{
|
||||||
|
move |(mut item_state, mut transaction), inventory_item| {
|
||||||
|
Box::pin(async move {
|
||||||
|
let mut inventory = item_state.inventory(&character_id)?;
|
||||||
|
let price = inventory_item.item.sell_price()?;
|
||||||
|
inventory.add_meseta_no_overflow(price)?;
|
||||||
|
|
||||||
|
let mut transaction = inventory_item.with_entity_id(transaction, |mut transaction, entity_id| {
|
||||||
|
async move {
|
||||||
|
transaction.gateway().add_item_note(&entity_id, ItemNote::SoldToShop).await?;
|
||||||
|
Ok(transaction)
|
||||||
|
}}).await?;
|
||||||
|
transaction.gateway().set_character_meseta(&character_id, inventory.meseta).await?;
|
||||||
|
item_state.set_inventory(inventory);
|
||||||
|
Ok(((item_state, transaction), inventory_item))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn sell_item<'a, EG> (
|
||||||
|
item_state: &'a mut ItemState,
|
||||||
|
entity_gateway: &mut EG,
|
||||||
|
character: &CharacterEntity,
|
||||||
|
item_id: ClientItemId,
|
||||||
|
amount: u32,
|
||||||
|
) -> Result<InventoryItem, ItemStateError>
|
||||||
|
where
|
||||||
|
EG: EntityGateway,
|
||||||
|
{
|
||||||
|
entity_gateway.with_transaction(|transaction| async move {
|
||||||
|
let item_state_proxy = ItemStateProxy::new(item_state);
|
||||||
|
let ((item_state_proxy, transaction), result) = ItemStateAction::default()
|
||||||
|
.act(take_item_from_inventory(character.id, item_id, amount))
|
||||||
|
.act(sell_inventory_item(character.id))
|
||||||
|
.commit((item_state_proxy, transaction))
|
||||||
|
.await?;
|
||||||
|
item_state_proxy.commit();
|
||||||
|
Ok((transaction, result))
|
||||||
|
}).await
|
||||||
|
}
|
||||||
|
@ -9,9 +9,10 @@ use crate::ship::map::MapArea;
|
|||||||
use crate::ship::location::{AreaClient, RoomId};
|
use crate::ship::location::{AreaClient, RoomId};
|
||||||
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
use crate::entity::character::{CharacterEntity, CharacterEntityId};
|
||||||
use crate::entity::gateway::{EntityGateway, GatewayError};
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::item::tool::Tool;
|
use crate::entity::item::tool::{Tool, ToolType};
|
||||||
use crate::entity::item::mag::Mag;
|
use crate::entity::item::mag::Mag;
|
||||||
use crate::ship::drops::ItemDrop;
|
use crate::ship::drops::ItemDrop;
|
||||||
|
use crate::ship::shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem};
|
||||||
|
|
||||||
// TODO: Commit trait that ItemStateProxy and EntityTransaction implement that .commit requires and acts on upon everything succeeding (like 3 less lines of code!)
|
// TODO: Commit trait that ItemStateProxy and EntityTransaction implement that .commit requires and acts on upon everything succeeding (like 3 less lines of code!)
|
||||||
|
|
||||||
@ -65,6 +66,9 @@ pub enum ItemStateError {
|
|||||||
|
|
||||||
#[error("item is not mag food {0}")]
|
#[error("item is not mag food {0}")]
|
||||||
NotMagFood(ClientItemId),
|
NotMagFood(ClientItemId),
|
||||||
|
|
||||||
|
#[error("item is not sellable")]
|
||||||
|
ItemNotSellable,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum FloorType {
|
pub enum FloorType {
|
||||||
@ -299,6 +303,64 @@ impl InventoryItemDetail {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this should probably go somewhere a bit more fundamental like ItemDetail
|
||||||
|
pub fn sell_price(&self) -> Result<u32, ItemStateError> {
|
||||||
|
match self {
|
||||||
|
InventoryItemDetail::Individual(individual_item) => {
|
||||||
|
match &individual_item.item {
|
||||||
|
// TODO: can wrapped items be sold?
|
||||||
|
ItemDetail::Weapon(w) => {
|
||||||
|
if !w.tekked {
|
||||||
|
return Ok(1u32)
|
||||||
|
}
|
||||||
|
if w.is_rare_item() {
|
||||||
|
return Ok(10u32)
|
||||||
|
}
|
||||||
|
Ok((WeaponShopItem::from(w).price() / 8) as u32)
|
||||||
|
},
|
||||||
|
ItemDetail::Armor(a) => {
|
||||||
|
if a.is_rare_item() {
|
||||||
|
return Ok(10u32)
|
||||||
|
}
|
||||||
|
Ok((ArmorShopItem::from(a).price() / 8) as u32)
|
||||||
|
},
|
||||||
|
ItemDetail::Shield(s) => {
|
||||||
|
if s.is_rare_item() {
|
||||||
|
return Ok(10u32)
|
||||||
|
}
|
||||||
|
Ok((ArmorShopItem::from(s).price() / 8) as u32)
|
||||||
|
},
|
||||||
|
ItemDetail::Unit(u) => {
|
||||||
|
if u.is_rare_item() {
|
||||||
|
return Ok(10u32)
|
||||||
|
}
|
||||||
|
Ok((ArmorShopItem::from(u).price() / 8) as u32)
|
||||||
|
},
|
||||||
|
ItemDetail::Tool(t) => {
|
||||||
|
if !matches!(t.tool, ToolType::PhotonDrop | ToolType::PhotonSphere | ToolType::PhotonCrystal) && t.is_rare_item() {
|
||||||
|
return Ok(10u32)
|
||||||
|
}
|
||||||
|
Ok((ToolShopItem::from(t).price() / 8) as u32)
|
||||||
|
},
|
||||||
|
ItemDetail::TechniqueDisk(d) => {
|
||||||
|
Ok((ToolShopItem::from(d).price() / 8) as u32)
|
||||||
|
},
|
||||||
|
ItemDetail::Mag(_m) => {
|
||||||
|
Err(ItemStateError::ItemNotSellable)
|
||||||
|
},
|
||||||
|
ItemDetail::ESWeapon(_e) => {
|
||||||
|
Ok(10u32)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// the number of stacked items sold is handled by the caller. this is just the price of 1
|
||||||
|
InventoryItemDetail::Stacked(stacked_item) => {
|
||||||
|
Ok(((ToolShopItem::from(&stacked_item.tool).price() / 8) as u32) * stacked_item.count() as u32)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use crate::ship::location::{ClientLocation, ClientLocationError};
|
|||||||
use crate::ship::items::{ItemManager, ClientItemId};
|
use crate::ship::items::{ItemManager, ClientItemId};
|
||||||
use crate::ship::packet::builder;
|
use crate::ship::packet::builder;
|
||||||
use crate::ship::items::state::ItemState;
|
use crate::ship::items::state::ItemState;
|
||||||
use crate::ship::items::actions::{drop_item, drop_partial_item, drop_meseta, equip_item, unequip_item, sort_inventory, use_item, feed_mag};
|
use crate::ship::items::actions::{drop_item, drop_partial_item, drop_meseta, equip_item, unequip_item, sort_inventory, use_item, feed_mag, sell_item};
|
||||||
|
|
||||||
pub async fn request_exp<EG: EntityGateway>(id: ClientId,
|
pub async fn request_exp<EG: EntityGateway>(id: ClientId,
|
||||||
request_exp: &RequestExp,
|
request_exp: &RequestExp,
|
||||||
@ -404,7 +404,7 @@ where
|
|||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
//item_manager.player_sells_item(entity_gateway, &mut client.character, ClientItemId(sold_item.item_id), sold_item.amount as usize).await?;
|
sell_item(item_state, entity_gateway, &client.character, ClientItemId(sold_item.item_id), sold_item.amount as u32).await?;
|
||||||
// TODO: send the packet to other clients
|
// TODO: send the packet to other clients
|
||||||
Ok(Box::new(None.into_iter()))
|
Ok(Box::new(None.into_iter()))
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use elseware::entity::item;
|
|||||||
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
|
use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket};
|
||||||
use elseware::ship::room::Difficulty;
|
use elseware::ship::room::Difficulty;
|
||||||
use elseware::ship::items::manager::ItemManagerError;
|
use elseware::ship::items::manager::ItemManagerError;
|
||||||
|
use elseware::ship::items::state::ItemStateError;
|
||||||
|
|
||||||
use libpso::packet::ship::*;
|
use libpso::packet::ship::*;
|
||||||
use libpso::packet::messages::*;
|
use libpso::packet::messages::*;
|
||||||
@ -1142,7 +1143,7 @@ async fn test_player_cant_sell_if_meseta_would_go_over_max() {
|
|||||||
item_id: 0x10000,
|
item_id: 0x10000,
|
||||||
amount: 1,
|
amount: 1,
|
||||||
})))).await.err().unwrap();
|
})))).await.err().unwrap();
|
||||||
assert!(matches!(ack.downcast::<ItemManagerError>().unwrap(), ItemManagerError::WalletFull));
|
assert!(matches!(ack.downcast::<ItemStateError>().unwrap(), ItemStateError::FullOfMeseta));
|
||||||
|
|
||||||
let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
|
let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap();
|
||||||
assert_eq!(c1_meseta.0, 999995);
|
assert_eq!(c1_meseta.0, 999995);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user