refactor tekking
This commit is contained in:
parent
4a6bd47c9e
commit
8f44ca9d18
@ -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())
|
||||
|
@ -567,10 +567,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