refactor tekking
This commit is contained in:
		
							parent
							
								
									b0b34b6616
								
							
						
					
					
						commit
						9c878ed484
					
				| @ -334,3 +334,8 @@ pub struct TradeEntity { | ||||
|     pub character1: CharacterEntityId, | ||||
|     pub character2: CharacterEntityId, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub enum ItemModifier { | ||||
|     WeaponModifier(weapon::WeaponModifier), | ||||
| } | ||||
|  | ||||
| @ -11,6 +11,8 @@ use crate::ship::items::state::{ItemState, ItemStateProxy, ItemStateAction, Item | ||||
| use crate::ship::items::apply_item::apply_item; | ||||
| use crate::entity::item::{ItemDetail, NewItemEntity, TradeId}; | ||||
| use crate::entity::item::tool::Tool; | ||||
| use crate::entity::item::weapon::WeaponModifier; | ||||
| use crate::entity::item::ItemModifier; | ||||
| use crate::ship::shops::ShopItem; | ||||
| use crate::ship::trade::TradeItem; | ||||
| use crate::ship::location::{AreaClient, RoomId}; | ||||
| @ -1281,3 +1283,65 @@ where | ||||
|         Ok((transaction, floor_item)) | ||||
|     }).await | ||||
| } | ||||
| 
 | ||||
| fn apply_modifier_to_inventory_item(character_id: CharacterEntityId, modifier: ItemModifier) | ||||
|                         -> impl for<'a> 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 |(item_state, mut transaction), mut inventory_item| { | ||||
|         let modifier = modifier.clone(); | ||||
|         Box::pin(async move { | ||||
|             match (&inventory_item.item, modifier) { | ||||
|                 (InventoryItemDetail::Individual(IndividualItemDetail{entity_id, item: ItemDetail::Weapon(mut weapon), ..}), ItemModifier::WeaponModifier(modifier)) => { | ||||
|                     weapon.apply_modifier(&modifier); | ||||
|                     transaction.gateway().add_weapon_modifier(&entity_id, modifier).await?; | ||||
|                 }, | ||||
|                 _ => return Err(ItemStateError::InvalidModifier) | ||||
|             } | ||||
| 
 | ||||
|             Ok(((item_state, transaction), inventory_item)) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn as_individual_item() | ||||
|                       -> impl for<'a> Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction + 'a>), InventoryItem) | ||||
|                                          -> Pin<Box<dyn Future<Output=Result<((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction + 'a>), IndividualItemDetail), ItemStateError>> + Send + 'a>> | ||||
| { | ||||
|     move |(item_state, transaction), inventory_item| { | ||||
|         Box::pin(async move { | ||||
|             let item = match inventory_item.item { | ||||
|                 InventoryItemDetail::Individual(individual_item) => individual_item, | ||||
|                 _ => return Err(ItemStateError::WrongItemType(inventory_item.item_id)) | ||||
|             }; | ||||
| 
 | ||||
|             Ok(((item_state, transaction), item)) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| pub async fn apply_modifier<'a, EG> ( | ||||
|     item_state: &'a mut ItemState, | ||||
|     entity_gateway: &mut EG, | ||||
|     character: &CharacterEntity, | ||||
|     item_id: ClientItemId, | ||||
|     modifier: ItemModifier) | ||||
|     -> Result<IndividualItemDetail, ItemStateError> | ||||
| where | ||||
|     EG: EntityGateway, | ||||
| { | ||||
|     entity_gateway.with_transaction(|transaction| async move { | ||||
|         let item_state_proxy = ItemStateProxy::new(item_state); | ||||
|         let ((item_state_proxy, transaction), item) = ItemStateAction::default() | ||||
|             .act(take_item_from_inventory(character.id, item_id, 1)) | ||||
|             .act(apply_modifier_to_inventory_item(character.id, modifier)) | ||||
|             .act(add_item_to_inventory(character.clone())) | ||||
|             .act(as_individual_item()) | ||||
|             .commit((item_state_proxy, transaction)) | ||||
|             .await?; | ||||
| 
 | ||||
|             item_state_proxy.commit(); | ||||
|         Ok((transaction, item)) | ||||
|     }).await | ||||
| } | ||||
|  | ||||
| @ -10,6 +10,7 @@ use crate::ship::location::{AreaClient, RoomId}; | ||||
| use crate::entity::character::{CharacterEntity, CharacterEntityId}; | ||||
| use crate::entity::gateway::{EntityGateway, GatewayError}; | ||||
| use crate::entity::item::tool::{Tool, ToolType}; | ||||
| use crate::entity::item::weapon::Weapon; | ||||
| use crate::entity::item::mag::Mag; | ||||
| use crate::ship::drops::ItemDrop; | ||||
| use crate::ship::shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem}; | ||||
| @ -69,6 +70,12 @@ pub enum ItemStateError { | ||||
| 
 | ||||
|     #[error("item is not sellable")] | ||||
|     ItemNotSellable, | ||||
| 
 | ||||
|     #[error("could not modify item")] | ||||
|     InvalidModifier, | ||||
| 
 | ||||
|     #[error("wrong item type ")] | ||||
|     WrongItemType(ClientItemId), | ||||
| } | ||||
| 
 | ||||
| pub enum FloorType { | ||||
| @ -221,6 +228,13 @@ pub struct IndividualItemDetail { | ||||
| } | ||||
| 
 | ||||
| impl IndividualItemDetail { | ||||
|     pub fn as_weapon(&self) -> Option<&Weapon> { | ||||
|         match &self.item { | ||||
|             ItemDetail::Weapon(weapon) => Some(weapon), | ||||
|             _ => None | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn as_mag(&self) -> Option<&Mag> { | ||||
|         match &self.item { | ||||
|             ItemDetail::Mag(mag) => Some(mag), | ||||
| @ -234,6 +248,20 @@ impl IndividualItemDetail { | ||||
|             _ => None | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn as_client_bytes(&self) -> [u8; 16] { | ||||
|         match &self.item { | ||||
|             ItemDetail::Weapon(w) => w.as_bytes(), | ||||
|             ItemDetail::Armor(a) => a.as_bytes(), | ||||
|             ItemDetail::Shield(s) => s.as_bytes(), | ||||
|             ItemDetail::Unit(u) => u.as_bytes(), | ||||
|             ItemDetail::Tool(t) => t.as_individual_bytes(), | ||||
|             ItemDetail::TechniqueDisk(d) => d.as_bytes(), | ||||
|             ItemDetail::Mag(m) => m.as_bytes(), | ||||
|             ItemDetail::ESWeapon(e) => e.as_bytes(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| @ -287,16 +315,7 @@ impl InventoryItemDetail { | ||||
|     pub fn as_client_bytes(&self) -> [u8; 16] { | ||||
|         match self { | ||||
|             InventoryItemDetail::Individual(item) => { | ||||
|                 match &item.item { | ||||
|                     ItemDetail::Weapon(w) => w.as_bytes(), | ||||
|                     ItemDetail::Armor(a) => a.as_bytes(), | ||||
|                     ItemDetail::Shield(s) => s.as_bytes(), | ||||
|                     ItemDetail::Unit(u) => u.as_bytes(), | ||||
|                     ItemDetail::Tool(t) => t.as_individual_bytes(), | ||||
|                     ItemDetail::TechniqueDisk(d) => d.as_bytes(), | ||||
|                     ItemDetail::Mag(m) => m.as_bytes(), | ||||
|                     ItemDetail::ESWeapon(e) => e.as_bytes(), | ||||
|                 } | ||||
|                 item.as_client_bytes() | ||||
|             }, | ||||
|             InventoryItemDetail::Stacked(item) => { | ||||
|                 item.tool.as_stacked_bytes(item.entity_ids.len()) | ||||
|  | ||||
| @ -6,7 +6,7 @@ use crate::ship::ship::{ShipError}; | ||||
| use crate::ship::items::{ClientItemId, InventoryItem, StackedFloorItem, FloorItem, CharacterBank}; | ||||
| use crate::ship::items::state::FloorItem as FloorItem2; | ||||
| use crate::ship::items::state::InventoryItem as InventoryItem2; | ||||
| use crate::ship::items::state::{BankState}; | ||||
| use crate::ship::items::state::{BankState, IndividualItemDetail}; | ||||
| use crate::ship::location::AreaClient; | ||||
| use std::convert::TryInto; | ||||
| use crate::ship::shops::ShopItem; | ||||
| @ -31,7 +31,7 @@ pub fn item_drop(client: u8, target: u8, item_drop: &FloorItem2) -> Result<ItemD | ||||
| } | ||||
| 
 | ||||
| // TODO: this doesn't need to be a Result, just unwrap try_intos they are guaranteed to succeed
 | ||||
| pub fn create_individual_item(area_client: AreaClient, item_id: ClientItemId, item: &item::ItemDetail) -> Result<CreateItem, ShipError> { | ||||
| pub fn create_individual_item(area_client: AreaClient, item_id: ClientItemId, item: &IndividualItemDetail) -> Result<CreateItem, ShipError> { | ||||
|     let bytes = item.as_client_bytes(); | ||||
|     Ok(CreateItem { | ||||
|         client: area_client.local_client.id(), | ||||
|  | ||||
| @ -15,7 +15,7 @@ use libpso::utf8_to_utf16_array; | ||||
| use crate::ship::packet::builder; | ||||
| use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem}; | ||||
| use crate::ship::items::state::{ItemState, FloorType, FloorItemDetail}; | ||||
| use crate::ship::items::actions::{pick_up_item, withdraw_meseta, deposit_meseta, withdraw_item, deposit_item, buy_shop_item, enemy_drops_item, TriggerCreateItem}; | ||||
| use crate::ship::items::actions::{pick_up_item, withdraw_meseta, deposit_meseta, withdraw_item, deposit_item, buy_shop_item, enemy_drops_item, take_meseta, apply_modifier, TriggerCreateItem}; | ||||
| 
 | ||||
| const BANK_ACTION_DEPOSIT: u8 = 0; | ||||
| const BANK_ACTION_WITHDRAW: u8 = 1; | ||||
| @ -151,7 +151,7 @@ where | ||||
|     let (item, floor_type) = item_state.get_floor_item(&client.character.id, &ClientItemId(pickup_item.item_id))?; | ||||
|     let remove_item = builder::message::remove_item_from_floor(area_client, item)?; | ||||
|     let create_item = match &item.item { | ||||
|         FloorItemDetail::Individual(individual_floor_item) => Some(builder::message::create_individual_item(area_client, item.item_id, &individual_floor_item.item)?), | ||||
|         FloorItemDetail::Individual(individual_floor_item) => Some(builder::message::create_individual_item(area_client, item.item_id, individual_floor_item)?), | ||||
|         FloorItemDetail::Stacked(stacked_floor_item) => Some(builder::message::create_stacked_item(area_client, item.item_id, &stacked_floor_item.tool, stacked_floor_item.count())?), | ||||
|         FloorItemDetail::Meseta(_) => None, | ||||
|         //_ => Some(builder::message::create_item(area_client, &item)?),
 | ||||
| @ -411,7 +411,7 @@ pub async fn request_tek_item<EG>(id: ClientId, | ||||
|                                   tek_request: &TekRequest, | ||||
|                                   entity_gateway: &mut EG, | ||||
|                                   clients: &mut Clients, | ||||
|                                   item_manager: &mut ItemManager) | ||||
|                                   item_state: &mut ItemState) | ||||
|                                   -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> | ||||
| where | ||||
|     EG: EntityGateway | ||||
| @ -429,13 +429,14 @@ where | ||||
| 
 | ||||
|     client.tek = Some((ClientItemId(tek_request.item_id), special_mod, percent_mod, grind_mod)); | ||||
| 
 | ||||
|     let inventory = item_manager.get_character_inventory(&client.character)?; | ||||
|     let item = inventory.get_item_by_id(ClientItemId(tek_request.item_id)) | ||||
|     let inventory = item_state.get_character_inventory(&client.character)?; | ||||
|     let item = inventory.get_by_client_id(&ClientItemId(tek_request.item_id)) | ||||
|         .ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))?; | ||||
|     let mut weapon = *item.individual() | ||||
|     let mut weapon = item.item.as_individual() | ||||
|         .ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))? | ||||
|         .weapon() | ||||
|         .ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))?; | ||||
|         .as_weapon() | ||||
|         .ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))? | ||||
|         .clone(); | ||||
| 
 | ||||
|     weapon.apply_modifier(&item::weapon::WeaponModifier::Tekked { | ||||
|         special: special_mod, | ||||
| @ -443,9 +444,7 @@ where | ||||
|         grind: grind_mod, | ||||
|     }); | ||||
| 
 | ||||
|     let character_meseta = item_manager.get_character_meseta_mut(&client.character.id)?; | ||||
|     character_meseta.0 -= 100; | ||||
|     entity_gateway.set_character_meseta(&client.character.id, *character_meseta).await?; | ||||
|     take_meseta(item_state, entity_gateway, &client.character.id, item::Meseta(100)).await?; | ||||
| 
 | ||||
|     let preview_pkt = builder::message::tek_preview(ClientItemId(tek_request.item_id), &weapon)?; | ||||
| 
 | ||||
| @ -457,7 +456,7 @@ pub async fn accept_tek_item<EG>(id: ClientId, | ||||
|                                  entity_gateway: &mut EG, | ||||
|                                  client_location: &ClientLocation, | ||||
|                                  clients: &mut Clients, | ||||
|                                  item_manager: &mut ItemManager) | ||||
|                                  item_state: &mut ItemState) | ||||
|                                  -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> | ||||
| where | ||||
|     EG: EntityGateway | ||||
| @ -475,9 +474,9 @@ where | ||||
|             percent: percent_mod, | ||||
|             grind: grind_mod, | ||||
|         }; | ||||
|         let weapon = item_manager.replace_item_with_tekked(entity_gateway, &client.character, item_id, modifier).await?; | ||||
|         let weapon = apply_modifier(item_state, entity_gateway, &client.character, item_id, item::ItemModifier::WeaponModifier(modifier)).await?; | ||||
| 
 | ||||
|         let create_item_pkt = builder::message::create_individual_item(area_client, item_id, &item::ItemDetail::Weapon(weapon))?; | ||||
|         let create_item_pkt = builder::message::create_individual_item(area_client, item_id, &weapon)?; | ||||
| 
 | ||||
|         let neighbors = client_location.get_client_neighbors(id).map_err(|err| -> ClientLocationError { err.into() })?; | ||||
|         Ok(Box::new(neighbors.into_iter() | ||||
|  | ||||
| @ -512,7 +512,7 @@ where | ||||
|                         .map(|(client, item)| { | ||||
|                             match item.item { | ||||
|                                 InventoryItemDetail::Individual(individual_item) => { | ||||
|                                     GameMessage::CreateItem(builder::message::create_individual_item(client, item.item_id, &individual_item.item).unwrap()) | ||||
|                                     GameMessage::CreateItem(builder::message::create_individual_item(client, item.item_id, &individual_item).unwrap()) | ||||
|                                 }, | ||||
|                                 InventoryItemDetail::Stacked(stacked_item) => { | ||||
|                                     GameMessage::CreateItem(builder::message::create_stacked_item(client, item.item_id, &stacked_item.tool, stacked_item.count()).unwrap()) | ||||
|  | ||||
| @ -569,10 +569,10 @@ impl<EG: EntityGateway> ShipServerState<EG> { | ||||
|                 handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::TekRequest(tek_request) => { | ||||
|                 handler::direct_message::request_tek_item(id, tek_request, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await? | ||||
|                 handler::direct_message::request_tek_item(id, tek_request, &mut self.entity_gateway, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::TekAccept(tek_accept) => { | ||||
|                 handler::direct_message::accept_tek_item(id, tek_accept, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await? | ||||
|                 handler::direct_message::accept_tek_item(id, tek_accept, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::TradeRequest(trade_request) => { | ||||
|                 handler::trade::trade_request(id, trade_request, target, &block.client_location, &mut self.clients, &mut self.item_state, &mut self.trades).await? | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user