refactor tekking
This commit is contained in:
parent
b0b34b6616
commit
9c878ed484
@ -334,3 +334,8 @@ pub struct TradeEntity {
|
|||||||
pub character1: CharacterEntityId,
|
pub character1: CharacterEntityId,
|
||||||
pub character2: 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::ship::items::apply_item::apply_item;
|
||||||
use crate::entity::item::{ItemDetail, NewItemEntity, TradeId};
|
use crate::entity::item::{ItemDetail, NewItemEntity, TradeId};
|
||||||
use crate::entity::item::tool::Tool;
|
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::shops::ShopItem;
|
||||||
use crate::ship::trade::TradeItem;
|
use crate::ship::trade::TradeItem;
|
||||||
use crate::ship::location::{AreaClient, RoomId};
|
use crate::ship::location::{AreaClient, RoomId};
|
||||||
@ -1281,3 +1283,65 @@ where
|
|||||||
Ok((transaction, floor_item))
|
Ok((transaction, floor_item))
|
||||||
}).await
|
}).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::character::{CharacterEntity, CharacterEntityId};
|
||||||
use crate::entity::gateway::{EntityGateway, GatewayError};
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::item::tool::{Tool, ToolType};
|
use crate::entity::item::tool::{Tool, ToolType};
|
||||||
|
use crate::entity::item::weapon::Weapon;
|
||||||
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};
|
use crate::ship::shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem};
|
||||||
@ -69,6 +70,12 @@ pub enum ItemStateError {
|
|||||||
|
|
||||||
#[error("item is not sellable")]
|
#[error("item is not sellable")]
|
||||||
ItemNotSellable,
|
ItemNotSellable,
|
||||||
|
|
||||||
|
#[error("could not modify item")]
|
||||||
|
InvalidModifier,
|
||||||
|
|
||||||
|
#[error("wrong item type ")]
|
||||||
|
WrongItemType(ClientItemId),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum FloorType {
|
pub enum FloorType {
|
||||||
@ -221,6 +228,13 @@ pub struct IndividualItemDetail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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> {
|
pub fn as_mag(&self) -> Option<&Mag> {
|
||||||
match &self.item {
|
match &self.item {
|
||||||
ItemDetail::Mag(mag) => Some(mag),
|
ItemDetail::Mag(mag) => Some(mag),
|
||||||
@ -234,6 +248,20 @@ impl IndividualItemDetail {
|
|||||||
_ => None
|
_ => 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)]
|
#[derive(Clone, Debug)]
|
||||||
@ -287,16 +315,7 @@ impl InventoryItemDetail {
|
|||||||
pub fn as_client_bytes(&self) -> [u8; 16] {
|
pub fn as_client_bytes(&self) -> [u8; 16] {
|
||||||
match self {
|
match self {
|
||||||
InventoryItemDetail::Individual(item) => {
|
InventoryItemDetail::Individual(item) => {
|
||||||
match &item.item {
|
item.as_client_bytes()
|
||||||
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(),
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
InventoryItemDetail::Stacked(item) => {
|
InventoryItemDetail::Stacked(item) => {
|
||||||
item.tool.as_stacked_bytes(item.entity_ids.len())
|
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::{ClientItemId, InventoryItem, StackedFloorItem, FloorItem, CharacterBank};
|
||||||
use crate::ship::items::state::FloorItem as FloorItem2;
|
use crate::ship::items::state::FloorItem as FloorItem2;
|
||||||
use crate::ship::items::state::InventoryItem as InventoryItem2;
|
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 crate::ship::location::AreaClient;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use crate::ship::shops::ShopItem;
|
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
|
// 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();
|
let bytes = item.as_client_bytes();
|
||||||
Ok(CreateItem {
|
Ok(CreateItem {
|
||||||
client: area_client.local_client.id(),
|
client: area_client.local_client.id(),
|
||||||
|
@ -15,7 +15,7 @@ use libpso::utf8_to_utf16_array;
|
|||||||
use crate::ship::packet::builder;
|
use crate::ship::packet::builder;
|
||||||
use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem};
|
use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem};
|
||||||
use crate::ship::items::state::{ItemState, FloorType, FloorItemDetail};
|
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_DEPOSIT: u8 = 0;
|
||||||
const BANK_ACTION_WITHDRAW: u8 = 1;
|
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 (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 remove_item = builder::message::remove_item_from_floor(area_client, item)?;
|
||||||
let create_item = match &item.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::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,
|
FloorItemDetail::Meseta(_) => None,
|
||||||
//_ => Some(builder::message::create_item(area_client, &item)?),
|
//_ => Some(builder::message::create_item(area_client, &item)?),
|
||||||
@ -411,7 +411,7 @@ pub async fn request_tek_item<EG>(id: ClientId,
|
|||||||
tek_request: &TekRequest,
|
tek_request: &TekRequest,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_manager: &mut ItemManager)
|
item_state: &mut ItemState)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||||
where
|
where
|
||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
@ -429,13 +429,14 @@ where
|
|||||||
|
|
||||||
client.tek = Some((ClientItemId(tek_request.item_id), special_mod, percent_mod, grind_mod));
|
client.tek = Some((ClientItemId(tek_request.item_id), special_mod, percent_mod, grind_mod));
|
||||||
|
|
||||||
let inventory = item_manager.get_character_inventory(&client.character)?;
|
let inventory = item_state.get_character_inventory(&client.character)?;
|
||||||
let item = inventory.get_item_by_id(ClientItemId(tek_request.item_id))
|
let item = inventory.get_by_client_id(&ClientItemId(tek_request.item_id))
|
||||||
.ok_or(ItemManagerError::WrongItemType(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)))?
|
.ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))?
|
||||||
.weapon()
|
.as_weapon()
|
||||||
.ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))?;
|
.ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))?
|
||||||
|
.clone();
|
||||||
|
|
||||||
weapon.apply_modifier(&item::weapon::WeaponModifier::Tekked {
|
weapon.apply_modifier(&item::weapon::WeaponModifier::Tekked {
|
||||||
special: special_mod,
|
special: special_mod,
|
||||||
@ -443,9 +444,7 @@ where
|
|||||||
grind: grind_mod,
|
grind: grind_mod,
|
||||||
});
|
});
|
||||||
|
|
||||||
let character_meseta = item_manager.get_character_meseta_mut(&client.character.id)?;
|
take_meseta(item_state, entity_gateway, &client.character.id, item::Meseta(100)).await?;
|
||||||
character_meseta.0 -= 100;
|
|
||||||
entity_gateway.set_character_meseta(&client.character.id, *character_meseta).await?;
|
|
||||||
|
|
||||||
let preview_pkt = builder::message::tek_preview(ClientItemId(tek_request.item_id), &weapon)?;
|
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,
|
entity_gateway: &mut EG,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_manager: &mut ItemManager)
|
item_state: &mut ItemState)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||||
where
|
where
|
||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
@ -475,9 +474,9 @@ where
|
|||||||
percent: percent_mod,
|
percent: percent_mod,
|
||||||
grind: grind_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() })?;
|
let neighbors = client_location.get_client_neighbors(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
Ok(Box::new(neighbors.into_iter()
|
Ok(Box::new(neighbors.into_iter()
|
||||||
|
@ -512,7 +512,7 @@ where
|
|||||||
.map(|(client, item)| {
|
.map(|(client, item)| {
|
||||||
match item.item {
|
match item.item {
|
||||||
InventoryItemDetail::Individual(individual_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) => {
|
InventoryItemDetail::Stacked(stacked_item) => {
|
||||||
GameMessage::CreateItem(builder::message::create_stacked_item(client, item.item_id, &stacked_item.tool, stacked_item.count()).unwrap())
|
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?
|
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) => {
|
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) => {
|
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) => {
|
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?
|
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