@ -6,7 +6,10 @@ use std::pin::Pin;
use crate ::ship ::map ::MapArea ;
use crate ::entity ::character ::{ CharacterEntity , CharacterEntityId } ;
use crate ::entity ::gateway ::{ EntityGateway , EntityGatewayTransaction } ;
use crate ::ship ::items ::state ::{ ItemState , ItemStateProxy , ItemStateAction , ItemAction , ItemStateError , FloorItem , InventoryItem , AddItemResult , FloorItemDetail , StackedItemDetail } ;
use crate ::ship ::items ::state ::{ ItemState , ItemStateProxy , ItemStateAction , ItemAction , ItemStateError , FloorItem , InventoryItem , AddItemResult , FloorItemDetail ,
StackedItemDetail , BankItem , BankItemDetail , InventoryItemDetail } ;
pub enum TriggerCreateItem {
Yes ,
@ -94,14 +97,14 @@ where
} ) . await
}
fn take_item_from_inventory ( character_id : CharacterEntityId , item_id : ClientItemId )
fn take_item_from_inventory ( character_id : CharacterEntityId , item_id : ClientItemId , amount : u32 )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , InventoryItem ) , ItemStateError > > + Send + 'a > >
{
move | ( mut item_state , mut transaction ) , _ | {
Box ::pin ( async move {
let mut inventory = item_state . inventory ( & character_id ) ? ;
let item = inventory . take_item ( & item_id ) . ok_or_else ( | | ItemStateError ::NoFloorItem ( item_id ) ) ? ;
let item = inventory . take_item ( & item_id , amount ) . ok_or_else ( | | ItemStateError ::NoFloorItem ( item_id ) ) ? ;
transaction . gateway ( ) . set_character_inventory ( & character_id , & inventory . as_inventory_entity ( & character_id ) ) . await ? ;
item_state . set_inventory ( inventory ) ;
@ -114,7 +117,7 @@ fn take_item_from_inventory(character_id: CharacterEntityId, item_id: ClientItem
fn add_inventory_item_to_shared_floor ( character_id : CharacterEntityId , map_area : MapArea , drop_position : ( f32 , f32 , f32 ) )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , InventoryItem )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) ) , ItemStateError > > + Send + 'a > >
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , FloorItem ) , ItemStateError > > + Send + 'a > >
{
move | ( mut item_state , transaction ) , inventory_item | {
Box ::pin ( async move {
@ -133,10 +136,10 @@ fn add_inventory_item_to_shared_floor(character_id: CharacterEntityId, map_area:
} } ) . await ? ;
let mut floor = item_state . floor ( & character_id ) ? ;
floor . add_inventory_item ( inventory_item , map_area , drop_position ) ;
let floor_item = floor . add_inventory_item ( inventory_item , map_area , drop_position ) . clone ( ) ;
item_state . set_floor ( floor ) ;
Ok ( ( ( item_state , transaction ) , ( ) ) )
Ok ( ( ( item_state , transaction ) , floor_item ) )
} )
}
}
@ -148,14 +151,14 @@ pub async fn drop_item<EG>(
item_id : & ClientItemId ,
map_area : MapArea ,
drop_position : ( f32 , f32 , f32 ) )
-> Result < ( ) , ItemStateError >
-> Result < FloorItem , 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 ) )
. act ( take_item_from_inventory ( character . id , * item_id , 1 ) )
. act ( add_inventory_item_to_shared_floor ( character . id , map_area , drop_position ) )
. commit ( ( item_state_proxy , transaction ) )
. await ? ;
@ -164,53 +167,62 @@ where
} ) . await
}
pub async fn drop_partial_item < 'a , EG > (
item_state : & 'a mut ItemState ,
entity_gateway : & mut EG ,
character : & CharacterEntity ,
item_id : & ClientItemId ,
map_area : MapArea ,
drop_position : ( f32 , f32 ) ,
amount : u32 )
-> Result < FloorItem , 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 ( add_inventory_item_to_shared_floor ( character . id , map_area , ( drop_position . 0 , 0.0 , drop_position . 1 ) ) )
. commit ( ( item_state_proxy , transaction ) )
. await ? ;
item_state_proxy . commit ( ) ;
Ok ( ( transaction , result ) )
} ) . await
}
fn take_partial_item_from_inventory ( character_id : CharacterEntityId , item_id : ClientItemId , amount : u32 )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , StackedItemDetail ) , ItemStateError > > + Send + 'a > >
fn take_meseta _from_inventory ( character_id : CharacterEntityId , amount : u32 )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) ) , ItemStateError > > + Send + 'a > >
{
move | ( mut item_state , mut transaction ) , _ | {
Box ::pin ( async move {
let mut inventory = item_state . inventory ( & character_id ) ? ;
let item = inventory . take_partial_item ( & item_id , amount ) . ok_or_else ( | | ItemStateError ::NoFloorItem ( item_id ) ) ? ;
transaction . gateway ( ) . set_character_inventory ( & character_id , & inventory . as_inventory_entity ( & character_id ) ) . await ? ;
item_state . set_inventory ( inventory ) ;
inventory . remove_meseta ( amount ) ? ;
transaction . gateway ( ) . set_character_meseta ( & character_id , inventory . meseta ) . await ? ;
Ok ( ( ( item_state , transaction ) , item ) )
Ok ( ( ( item_state , transaction ) , ( ) ) )
} )
}
}
fn add_partial_inventory_item_to_shared_floor ( character_id : CharacterEntityId , map_area : MapArea , drop_position : ( f32 , f32 ) )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , StackedItemDetail )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , FloorItem ) , ItemStateError > > + Send + 'a > >
fn add_meseta _to_shared_floor ( character_id : CharacterEntityId , amount : u32 , map_area : MapArea , drop_position : ( f32 , f32 ) )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , FloorItem ) , ItemStateError > > + Send + 'a > >
{
move | ( mut item_state , transaction ) , stacked_item | {
move | ( mut item_state , transaction ) , _ | {
Box ::pin ( async move {
let floor_item = FloorItem {
item_id : item_state . new_item_id ( ) ? ,
item : FloorItemDetail ::Stacked ( stacked_item ) ,
map_area ,
item : FloorItemDetail ::Meseta ( Meseta ( amount ) ) ,
map_area : map_area ,
x : drop_position . 0 ,
y : 0.0 ,
z : drop_position . 1 ,
} ;
let transaction = floor_item . with_entity_id ( Ok ( transaction ) , | mut transaction : Result < _ , ItemStateError > , entity_id | {
async move {
if let Ok ( transaction ) = & mut transaction {
transaction . gateway ( ) . add_item_note ( & entity_id , ItemNote ::PlayerDrop {
character_id ,
map_area ,
x : drop_position . 0 ,
y : 0.0 ,
z : drop_position . 1 ,
} ) . await ? ;
}
transaction
} } ) . await ? ;
let mut floor = item_state . floor ( & character_id ) ? ;
let floor_item = floor . add_item ( floor_item ) . clone ( ) ;
item_state . set_floor ( floor ) ;
@ -220,11 +232,10 @@ fn add_partial_inventory_item_to_shared_floor(character_id: CharacterEntityId, m
}
}
pub async fn drop_partial_item < 'a , EG > (
pub async fn drop_meseta < 'a , EG > (
item_state : & 'a mut ItemState ,
entity_gateway : & mut EG ,
character : & CharacterEntity ,
item_id : & ClientItemId ,
map_area : MapArea ,
drop_position : ( f32 , f32 ) ,
amount : u32 )
@ -235,8 +246,8 @@ where
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_partial_item _from_inventory ( character . id , * item_ id, amount ) )
. act ( add_partial_inventory_item _to_shared_floor ( character . id , map_area , drop_position ) )
. act ( take_meseta _from_inventory ( character . id , amount ) )
. act ( add_meseta _to_shared_floor ( character . id , amount , map_area , drop_position ) )
. commit ( ( item_state_proxy , transaction ) )
. await ? ;
item_state_proxy . commit ( ) ;
@ -245,62 +256,228 @@ where
}
fn take_meseta_from_inventory ( character_id : CharacterEntityId , amount : u32 )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , u32 ) , ItemStateError > > + Send + 'a > >
fn take_meseta_from_bank ( character_id : CharacterEntityId , amount : u32 )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) ) , ItemStateError > > + Send + 'a > >
{
move | ( mut item_state , mut transaction ) , _ | {
Box ::pin ( async move {
let mut bank = item_state . bank ( & character_id ) ? ;
bank . remove_meseta ( amount ) ? ;
transaction . gateway ( ) . set_bank_meseta ( & character_id , & bank . name , bank . meseta ) . await ? ;
Ok ( ( ( item_state , transaction ) , ( ) ) )
} )
}
}
fn add_meseta_from_bank_to_inventory ( character_id : CharacterEntityId , amount : u32 )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) ) , ItemStateError > > + Send + 'a > >
{
move | ( mut item_state , mut transaction ) , _ | {
Box ::pin ( async move {
let mut inventory = item_state . inventory ( & character_id ) ? ;
inventory . remove_meseta ( amount ) ? ;
inventory . add_meseta_no_overflow ( amount ) ? ;
transaction . gateway ( ) . set_character_meseta ( & character_id , inventory . meseta ) . await ? ;
Ok ( ( ( item_state , transaction ) , amount ) )
Ok ( ( ( item_state , transaction ) , ( ) ) )
} )
}
}
fn add_meseta_to_shared_floor ( character_id : CharacterEntityId , map_area : MapArea , drop_position : ( f32 , f32 ) )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , u32 )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , FloorItem ) , ItemStateError > > + Send + 'a > >
pub async fn withdraw_meseta < 'a , EG > (
item_state : & 'a mut ItemState ,
entity_gateway : & mut EG ,
character : & CharacterEntity ,
amount : u32 )
-> Result < ( ) , 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_meseta_from_bank ( character . id , amount ) )
. act ( add_meseta_from_bank_to_inventory ( character . id , amount ) )
. commit ( ( item_state_proxy , transaction ) )
. await ? ;
item_state_proxy . commit ( ) ;
Ok ( ( transaction , result ) )
} ) . await
}
move | ( mut item_state , transaction ) , amount | {
fn add_meseta_to_bank ( character_id : CharacterEntityId , amount : u32 )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) ) , ItemStateError > > + Send + 'a > >
{
move | ( mut item_state , mut transaction ) , _ | {
Box ::pin ( async move {
let floor_item = FloorItem {
item_id : item_state . new_item_id ( ) ? ,
item : FloorItemDetail ::Meseta ( Meseta ( amount ) ) ,
map_area : map_area ,
x : drop_position . 0 ,
y : 0.0 ,
z : drop_position . 1 ,
let mut bank = item_state . bank ( & character_id ) ? ;
bank . add_meseta ( amount ) ? ;
transaction . gateway ( ) . set_bank_meseta ( & character_id , & bank . name , bank . meseta ) . await ? ;
Ok ( ( ( item_state , transaction ) , ( ) ) )
} )
}
}
pub async fn deposit_meseta < 'a , EG > (
item_state : & 'a mut ItemState ,
entity_gateway : & mut EG ,
character : & CharacterEntity ,
amount : u32 )
-> Result < ( ) , 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_meseta_from_inventory ( character . id , amount ) )
. act ( add_meseta_to_bank ( character . id , amount ) )
. commit ( ( item_state_proxy , transaction ) )
. await ? ;
item_state_proxy . commit ( ) ;
Ok ( ( transaction , ( ) ) )
} ) . await
}
fn take_item_from_bank ( character_id : CharacterEntityId , item_id : ClientItemId , amount : u32 )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , BankItem ) , ItemStateError > > + Send + 'a > >
{
move | ( mut item_state , mut transaction ) , _ | {
Box ::pin ( async move {
let mut bank = item_state . bank ( & character_id ) ? ;
let item = bank . take_item ( & item_id , amount ) . ok_or_else ( | | ItemStateError ::NoBankItem ( item_id ) ) ? ;
transaction . gateway ( ) . set_character_bank ( & character_id , & bank . as_bank_entity ( ) , & bank . name ) . await ? ;
item_state . set_bank ( bank ) ;
Ok ( ( ( item_state , transaction ) , item ) )
} )
}
}
fn add_bank_item_to_inventory ( character : & CharacterEntity )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , BankItem )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , InventoryItem ) , ItemStateError > > + Send + 'a > >
{
let character = character . clone ( ) ;
move | ( mut item_state , transaction ) , bank_item | {
let character = character . clone ( ) ;
Box ::pin ( async move {
let bank_name = item_state . bank ( & character . id ) ? . name ;
let mut inventory = item_state . inventory ( & character . id ) ? ;
let character_id = character . id ;
let transaction = bank_item . with_entity_id ( Ok ( transaction ) , | mut transaction : Result < _ , ItemStateError > , entity_id | {
let bank_name = bank_name . clone ( ) ;
async move {
if let Ok ( transaction ) = & mut transaction {
transaction . gateway ( ) . add_item_note ( & entity_id , ItemNote ::Withdraw {
character_id ,
bank : bank_name ,
} ) . await ? ;
}
transaction
} } ) . await ? ;
let inventory_item = InventoryItem {
item_id : bank_item . item_id ,
item : match bank_item . item {
BankItemDetail ::Individual ( individual_item ) = > InventoryItemDetail ::Individual ( individual_item ) ,
BankItemDetail ::Stacked ( stacked_item ) = > InventoryItemDetail ::Stacked ( stacked_item ) ,
} ,
} ;
let mut floor = item_state . floor ( & character_id ) ? ;
let floor_item = floor . add_item ( floor_item ) . clone ( ) ;
item_state . set_floor ( floor ) ;
let mut transaction = inventory_item . with_mag ( Ok ( transaction ) , | mut transaction : Result < _ , ItemStateError > , entity_id , _mag | {
let character = character . clone ( ) ;
async move {
if let Ok ( transaction ) = & mut transaction {
transaction . gateway ( ) . change_mag_owner ( & entity_id , & character ) . await ? ;
}
transaction
} } ) . await ? ;
Ok ( ( ( item_state , transaction ) , floor_item ) )
inventory . add_item ( inventory_item . clone ( ) ) ? ;
transaction . gateway ( ) . set_character_inventory ( & character . id , & inventory . as_inventory_entity ( & character . id ) ) . await ? ;
item_state . set_inventory ( inventory ) ;
Ok ( ( ( item_state , transaction ) , inventory_item ) )
} )
}
}
pub async fn drop_meseta < 'a , EG > (
pub async fn withdraw_item < 'a , EG > (
item_state : & 'a mut ItemState ,
entity_gateway : & mut EG ,
character : & CharacterEntity ,
map_area : MapArea ,
drop_position : ( f32 , f32 ) ,
item_id : & ClientItemId ,
amount : u32 )
-> Result < FloorItem , ItemStateError >
-> Result < Inventory Item, 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_meseta_from_inventory ( character . id , amount ) )
. act ( add_meseta_to_shared_floor ( character . id , map_area , drop_position ) )
. act ( take_item_from_bank ( character . id , * item_id , amount ) )
. act ( add_bank_item_to_inventory ( & character ) )
. commit ( ( item_state_proxy , transaction ) )
. await ? ;
item_state_proxy . commit ( ) ;
Ok ( ( transaction , result ) )
} ) . await
}
fn add_inventory_item_to_bank ( character_id : CharacterEntityId )
-> impl for < 'a > Fn ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , InventoryItem )
-> Pin < Box < dyn Future < Output = Result < ( ( ItemStateProxy < 'a > , Box < dyn EntityGatewayTransaction + 'a > ) , ( ) ) , ItemStateError > > + Send + 'a > >
{
move | ( mut item_state , transaction ) , inventory_item | {
Box ::pin ( async move {
let mut bank = item_state . bank ( & character_id ) ? ;
let bank_name = bank . name . clone ( ) ;
let mut transaction = inventory_item . with_entity_id ( Ok ( transaction ) , move | mut transaction : Result < _ , ItemStateError > , entity_id | {
let bank_name = bank_name . clone ( ) ;
async move {
if let Ok ( transaction ) = & mut transaction {
transaction . gateway ( ) . add_item_note ( & entity_id , ItemNote ::Deposit {
character_id ,
bank : bank_name ,
} ) . await ? ;
}
transaction
} } ) . await ? ;
bank . add_inventory_item ( inventory_item ) ? ;
transaction . gateway ( ) . set_character_bank ( & character_id , & bank . as_bank_entity ( ) , & bank . name ) . await ? ;
item_state . set_bank ( bank ) ;
Ok ( ( ( item_state , transaction ) , ( ) ) )
} )
}
}
pub async fn deposit_item < 'a , EG > (
item_state : & 'a mut ItemState ,
entity_gateway : & mut EG ,
character : & CharacterEntity ,
item_id : & ClientItemId ,
amount : u32 )
-> Result < ( ) , 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 ( add_inventory_item_to_bank ( character . id ) )
. commit ( ( item_state_proxy , transaction ) )
. await ? ;
item_state_proxy . commit ( ) ;