Browse Source

enemy drop refactor

pull/113/head
jake 2 years ago
parent
commit
eb0689a1fe
  1. 138
      src/ship/items/actions.rs
  2. 7
      src/ship/items/state.rs
  3. 12
      src/ship/packet/builder/message.rs
  4. 14
      src/ship/packet/handler/direct_message.rs
  5. 4
      src/ship/ship.rs

138
src/ship/items/actions.rs

@ -10,9 +10,11 @@ use crate::ship::items::state::{ItemState, ItemStateProxy, ItemStateAction, Item
StackedItemDetail, BankItem, BankItemDetail, InventoryItemDetail, IndividualItemDetail}; StackedItemDetail, BankItem, BankItemDetail, InventoryItemDetail, IndividualItemDetail};
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::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};
use crate::ship::drops::{ItemDrop, ItemDropType};
pub enum TriggerCreateItem { pub enum TriggerCreateItem {
Yes, Yes,
@ -239,7 +241,7 @@ fn add_meseta_to_shared_floor(character_id: CharacterEntityId, amount: u32, map_
}; };
let mut floor = item_state.floor(&character_id)?; let mut floor = item_state.floor(&character_id)?;
let floor_item = floor.add_item(floor_item).clone();
let floor_item = floor.add_shared_item(floor_item).clone();
item_state.set_floor(floor); item_state.set_floor(floor);
Ok(((item_state, transaction), floor_item)) Ok(((item_state, transaction), floor_item))
@ -1145,3 +1147,137 @@ where
Ok((transaction, ())) Ok((transaction, ()))
}).await }).await
} }
fn convert_item_drop_to_floor_item(character_id: CharacterEntityId, item_drop: ItemDrop)
-> 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>> + Clone
{
move |(mut item_state, mut transaction), _| {
let item_drop = item_drop.clone();
Box::pin(async move {
enum ItemOrMeseta {
Individual(ItemDetail),
Stacked(Tool),
Meseta(Meseta)
}
let item = match item_drop.item {
ItemDropType::Weapon(w) => ItemOrMeseta::Individual(ItemDetail::Weapon(w)),
ItemDropType::Armor(w) => ItemOrMeseta::Individual(ItemDetail::Armor(w)),
ItemDropType::Shield(w) => ItemOrMeseta::Individual(ItemDetail::Shield(w)),
ItemDropType::Unit(w) => ItemOrMeseta::Individual(ItemDetail::Unit(w)),
ItemDropType::TechniqueDisk(w) => ItemOrMeseta::Individual(ItemDetail::TechniqueDisk(w)),
ItemDropType::Mag(w) => ItemOrMeseta::Individual(ItemDetail::Mag(w)),
ItemDropType::Tool(t) => {
if t.tool.is_stackable() {
ItemOrMeseta::Stacked(t)
}
else {
ItemOrMeseta::Individual(ItemDetail::Tool(t))
}
},
ItemDropType::Meseta(m) => ItemOrMeseta::Meseta(Meseta(m)),
};
let item_id = item_state.new_item_id()?;
let floor_item = match item {
ItemOrMeseta::Individual(item_detail) => {
let entity = transaction.gateway().create_item(NewItemEntity {
item: item_detail.clone(),
}).await?;
transaction.gateway().add_item_note(&entity.id, ItemNote::EnemyDrop {
character_id,
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
}).await?;
FloorItem {
item_id,
item: FloorItemDetail::Individual(IndividualItemDetail {
entity_id: entity.id,
item: item_detail,
}),
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
}
},
ItemOrMeseta::Stacked(tool) => {
let entity = transaction.gateway().create_item(NewItemEntity {
item: ItemDetail::Tool(tool),
}).await?;
transaction.gateway().add_item_note(&entity.id, ItemNote::EnemyDrop {
character_id,
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
}).await?;
FloorItem {
item_id,
item: FloorItemDetail::Stacked(StackedItemDetail{
entity_ids: vec![entity.id],
tool,
}),
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
}
},
ItemOrMeseta::Meseta(meseta) => {
FloorItem {
item_id,
item: FloorItemDetail::Meseta(meseta),
map_area: item_drop.map_area,
x: item_drop.x,
y: item_drop.y,
z: item_drop.z,
}
},
};
Ok(((item_state, transaction), floor_item))
})
}
}
fn add_item_to_local_floor(character_id: CharacterEntityId)
-> impl for<'a> Fn((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction + 'a>), FloorItem)
-> Pin<Box<dyn Future<Output=Result<((ItemStateProxy<'a>, Box<dyn EntityGatewayTransaction + 'a>), FloorItem), ItemStateError>> + Send + 'a>>
{
move |(mut item_state, transaction) , floor_item| {
Box::pin(async move {
let mut floor = item_state.floor(&character_id)?;
let item = floor.add_local_item(floor_item).clone();
item_state.set_floor(floor);
Ok(((item_state, transaction), item))
})
}
}
pub async fn enemy_drops_item<'a, EG> (
item_state: &'a mut ItemState,
entity_gateway: &mut EG,
character_id: CharacterEntityId,
item_drop: ItemDrop)
-> Result<FloorItem, ItemStateError>
where
EG: EntityGateway,
{
entity_gateway.with_transaction(|mut transaction| async move {
let item_state_proxy = ItemStateProxy::new(item_state);
let ((item_state_proxy, transaction), floor_item) = ItemStateAction::default()
.act(convert_item_drop_to_floor_item(character_id, item_drop))
.act(add_item_to_local_floor(character_id))
.commit((item_state_proxy, transaction))
.await?;
item_state_proxy.commit();
Ok((transaction, floor_item))
}).await
}

7
src/ship/items/state.rs

@ -1214,10 +1214,15 @@ impl FloorState {
&self.shared.0[self.shared.0.len()-1] &self.shared.0[self.shared.0.len()-1]
} }
pub fn add_item(&mut self, floor_item: FloorItem) -> &FloorItem {
pub fn add_shared_item(&mut self, floor_item: FloorItem) -> &FloorItem {
self.shared.0.push(floor_item); self.shared.0.push(floor_item);
&self.shared.0[self.shared.0.len()-1] &self.shared.0[self.shared.0.len()-1]
} }
pub fn add_local_item(&mut self, floor_item: FloorItem) -> &FloorItem {
self.local.0.push(floor_item);
&self.local.0[self.local.0.len()-1]
}
} }

12
src/ship/packet/builder/message.rs

@ -12,19 +12,19 @@ use std::convert::TryInto;
use crate::ship::shops::ShopItem; use crate::ship::shops::ShopItem;
pub fn item_drop(client: u8, target: u8, item_drop: &FloorItem) -> Result<ItemDrop, ShipError> {
pub fn item_drop(client: u8, target: u8, item_drop: &FloorItem2) -> Result<ItemDrop, ShipError> {
let item_bytes = item_drop.as_client_bytes(); let item_bytes = item_drop.as_client_bytes();
Ok(ItemDrop { Ok(ItemDrop {
client, client,
target, target,
map_area: item_drop.map_area().area_value(),
map_area: item_drop.map_area.area_value(),
variety: 0, variety: 0,
unknown: 0, unknown: 0,
x: item_drop.x(),
z: item_drop.z(),
y: item_drop.y(),
x: item_drop.x,
z: item_drop.z,
y: item_drop.y,
item_bytes: item_bytes[0..12].try_into()?, item_bytes: item_bytes[0..12].try_into()?,
item_id: item_drop.item_id().0,
item_id: item_drop.item_id.0,
item_bytes2: item_bytes[12..16].try_into()?, item_bytes2: item_bytes[12..16].try_into()?,
unknown2: 0, unknown2: 0,
}) })

14
src/ship/packet/handler/direct_message.rs

@ -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, TriggerCreateItem};
use crate::ship::items::actions::{pick_up_item, withdraw_meseta, deposit_meseta, withdraw_item, deposit_item, buy_shop_item, enemy_drops_item, 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;
@ -76,7 +76,7 @@ pub async fn request_item<EG>(id: ClientId,
client_location: &ClientLocation, client_location: &ClientLocation,
clients: &mut Clients, clients: &mut Clients,
rooms: &mut Rooms, rooms: &mut Rooms,
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
@ -111,8 +111,8 @@ where
item: item_drop, item: item_drop,
}; };
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await?;
let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, floor_item)?;
let floor_item = enemy_drops_item(item_state, entity_gateway, client.character.id, item_drop).await?;
let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?;
item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))); item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))));
} }
@ -195,7 +195,7 @@ pub async fn request_box_item<EG>(id: ClientId,
client_location: &ClientLocation, client_location: &ClientLocation,
clients: &mut Clients, clients: &mut Clients,
rooms: &mut Rooms, rooms: &mut Rooms,
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
@ -230,8 +230,8 @@ EG: EntityGateway
item: item_drop, item: item_drop,
}; };
let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?;
let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await?; // TODO: unwrap
let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, floor_item)?;
let floor_item = enemy_drops_item(item_state, entity_gateway, client.character.id, item_drop).await?;
let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?;
item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))) item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg)))))
} }

4
src/ship/ship.rs

@ -546,13 +546,13 @@ impl<EG: EntityGateway> ShipServerState<EG> {
handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients) handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients)
}, },
GameMessage::RequestItem(request_item) => { GameMessage::RequestItem(request_item) => {
handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await?
handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await?
}, },
GameMessage::PickupItem(pickup_item) => { GameMessage::PickupItem(pickup_item) => {
handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await?
}, },
GameMessage::BoxDropRequest(box_drop_request) => { GameMessage::BoxDropRequest(box_drop_request) => {
handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await?
handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await?
}, },
GameMessage::BankRequest(_bank_request) => { GameMessage::BankRequest(_bank_request) => {
handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_state).await? handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_state).await?

Loading…
Cancel
Save