From 9c28bd6a81f3a4ed2d0c754f32f3216d5156182d Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 30 Apr 2022 11:41:24 -0600 Subject: [PATCH] move drop item over to item_state --- src/ship/items/actions.rs | 69 +++++++++++++++++++++++++----- src/ship/packet/handler/message.rs | 16 ++++--- src/ship/ship.rs | 2 +- 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/src/ship/items/actions.rs b/src/ship/items/actions.rs index 09e6f1a..124b626 100644 --- a/src/ship/items/actions.rs +++ b/src/ship/items/actions.rs @@ -3,9 +3,10 @@ use crate::entity::item::ItemNote; use std::future::Future; use std::pin::Pin; +use crate::ship::map::MapArea; use crate::entity::character::{CharacterEntity, CharacterEntityId}; -use crate::entity::gateway::EntityGateway; -use crate::ship::items::state::{ItemState, ItemStateProxy, ItemStateAction, ItemAction, ItemStateError, FloorItem, AddItemResult}; +use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction}; +use crate::ship::items::state::{ItemState, ItemStateProxy, ItemStateAction, ItemAction, ItemStateError, FloorItem, InventoryItem, AddItemResult}; pub enum TriggerCreateItem {ItemAction, Yes, @@ -21,7 +22,7 @@ fn take_item_from_floor(character_id: CharacterEntityId, item_id: ClientItemId) let mut floor = item_state.floor(&character_id)?; let item = floor.take_item(&item_id).ok_or(ItemStateError::NoFloorItem(item_id))?; item_state.set_floor(floor); - + Ok(((item_state, transaction), item)) }) } @@ -71,6 +72,54 @@ fn add_floor_item_to_inventory(character: &CharacterEntity) } } + +fn take_item_from_inventory(character_id: CharacterEntityId, item_id: ClientItemId) + -> impl for<'a> Fn((ItemStateProxy<'a>, Box), ()) + -> Pin), 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))?; + + transaction.gateway().set_character_inventory(&character_id, &inventory.as_inventory_entity(&character_id)).await?; + item_state.set_inventory(inventory); + + Ok(((item_state, transaction), item)) + }) + } +} + + +fn add_inventory_item_to_shared_floor(character_id: CharacterEntityId, item_id: ClientItemId, map_area: MapArea, drop_position: (f32, f32, f32)) + -> impl for<'a> Fn((ItemStateProxy<'a>, Box), InventoryItem) + -> Pin), ()), ItemStateError>> + Send + 'a>> +{ + move |(mut item_state, transaction), inventory_item| { + Box::pin(async move { + let transaction = inventory_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: drop_position.1, + z: drop_position.2, + }).await?; + } + transaction + }}).await?; + + let mut floor = item_state.floor(&character_id)?; + floor.add_inventory_item(inventory_item, map_area, drop_position); + + Ok(((item_state, transaction), ())) + }) + } +} + + pub async fn pick_up_item( item_state: &mut ItemState, entity_gateway: &mut EG, @@ -96,23 +145,21 @@ pub async fn drop_item( item_state: &mut ItemState, entity_gateway: &mut EG, character: &CharacterEntity, - item_id: &ClientItemId) + item_id: &ClientItemId, + map_area: MapArea, + drop_position: (f32, f32, f32)) -> Result<(), ItemStateError> where EG: EntityGateway, { -/* - let result: Result = entity_gateway.with_transaction(|transaction| async move { + 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(add_inventory_item_to_shared_floor(&character)) + .act(add_inventory_item_to_shared_floor(character.id, *item_id, map_area, drop_position)) .commit((item_state_proxy, transaction)) .await?; item_state_proxy.commit(); Ok((transaction, result)) - }).await; - Ok(result?) - */ - Ok(()) + }).await } diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs index c39ba73..9ed1af9 100644 --- a/src/ship/packet/handler/message.rs +++ b/src/ship/packet/handler/message.rs @@ -7,6 +7,8 @@ use crate::ship::ship::{SendShipPacket, ShipError, Rooms, Clients, ItemDropLocat use crate::ship::location::{ClientLocation, ClientLocationError}; use crate::ship::items::{ItemManager, ClientItemId}; use crate::ship::packet::builder; +use crate::ship::items::state::ItemState; +use crate::ship::items::actions::{drop_item, pick_up_item}; pub async fn request_exp(id: ClientId, request_exp: &RequestExp, @@ -63,12 +65,12 @@ pub async fn request_exp(id: ClientId, } pub async fn player_drop_item(id: ClientId, - player_drop_item: &PlayerDropItem, - entity_gateway: &mut EG, - client_location: &ClientLocation, - clients: &mut Clients, - rooms: &mut Rooms, - item_manager: &mut ItemManager) + player_drop_item: &PlayerDropItem, + entity_gateway: &mut EG, + client_location: &ClientLocation, + clients: &mut Clients, + rooms: &mut Rooms, + item_state: &mut ItemState) -> Result + Send>, anyhow::Error> where EG: EntityGateway @@ -80,7 +82,7 @@ where .as_mut() .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; let area = room.map_areas.get_area_map(player_drop_item.map_area)?; - item_manager.player_drop_item_on_shared_floor(entity_gateway, &client.character, ClientItemId(player_drop_item.item_id), (*area, player_drop_item.x, player_drop_item.y, player_drop_item.z)).await?; + drop_item(item_state, entity_gateway, &client.character, &ClientItemId(player_drop_item.item_id), *area, (player_drop_item.x, player_drop_item.y, player_drop_item.z)).await?; let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; let pdi = player_drop_item.clone(); Ok(Box::new(clients_in_area.into_iter() diff --git a/src/ship/ship.rs b/src/ship/ship.rs index f7b8b5a..7dc371e 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -480,7 +480,7 @@ impl ShipServerState { }, GameMessage::PlayerDropItem(player_drop_item) => { let block = self.blocks.with_client(id, &self.clients)?; - handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await? + handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await? }, GameMessage::DropCoordinates(drop_coordinates) => { let block = self.blocks.with_client(id, &self.clients)?;