diff --git a/Cargo.lock b/Cargo.lock index c32fc6e..dfff310 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1040,7 +1040,6 @@ checksum = "739e9d7726dc32173fed2d69d17eef3c54682169e4e20ff1d0a45dcd37063cef" [[package]] name = "libpso" version = "0.1.0" -source = "git+http://git.sharnoth.com/jake/libpso#05222bbf9fe402675447bc163b45e07a327cdb1a" dependencies = [ "chrono", "psopacket", @@ -1399,7 +1398,6 @@ dependencies = [ [[package]] name = "psopacket" version = "1.0.0" -source = "git+http://git.sharnoth.com/jake/libpso#05222bbf9fe402675447bc163b45e07a327cdb1a" dependencies = [ "proc-macro2", "quote", diff --git a/src/entity/gateway/postgres/models.rs b/src/entity/gateway/postgres/models.rs index b017b3b..e1a6c8c 100644 --- a/src/entity/gateway/postgres/models.rs +++ b/src/entity/gateway/postgres/models.rs @@ -612,6 +612,9 @@ pub enum PgItemNoteDetail { Deposit { character_id: u32, bank: BankIdentifier, + }, + FloorLimitReached { + map_area: MapArea, } } @@ -658,7 +661,12 @@ impl From for PgItemNoteDetail { character_id: character_id.0, bank, } - } + }, + ItemNote::FloorLimitReached { map_area } => { + PgItemNoteDetail::FloorLimitReached { + map_area, + } + }, } } } @@ -703,6 +711,9 @@ impl From for ItemNote { character_id: CharacterEntityId(character_id), bank, }, + PgItemNoteDetail::FloorLimitReached { map_area } => ItemNote::FloorLimitReached { + map_area, + }, } } } diff --git a/src/entity/item/mod.rs b/src/entity/item/mod.rs index 6b7bf53..8b1d967 100644 --- a/src/entity/item/mod.rs +++ b/src/entity/item/mod.rs @@ -74,6 +74,9 @@ pub enum ItemNote { character_id: CharacterEntityId, bank: BankIdentifier, }, + FloorLimitReached { + map_area: MapArea, + }, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/src/ship/items/actions.rs b/src/ship/items/actions.rs index f9844bb..afdd044 100644 --- a/src/ship/items/actions.rs +++ b/src/ship/items/actions.rs @@ -1148,3 +1148,25 @@ where }) } } + +pub(super) fn delete_item_from_floor<'a, EG, TR>( + map_area: MapArea +) -> impl Fn((ItemStateProxy, TR), FloorItem) + -> BoxFuture<'a, Result<((ItemStateProxy, TR), ()), anyhow::Error>> +where + EG: EntityGateway, + TR: EntityGatewayTransaction + Clone + 'a, +{ + move |(item_state, transaction), floor_item| { + Box::pin(async move { + let transaction = floor_item.with_entity_id(transaction, |mut transaction, entity_id| { + async move { + transaction.gateway().add_item_note(&entity_id, ItemNote::FloorLimitReached { + map_area + }).await?; + Ok(transaction) + }}).await?; + Ok(((item_state, transaction), ())) + }) + } +} \ No newline at end of file diff --git a/src/ship/items/tasks.rs b/src/ship/items/tasks.rs index 3e0cf6a..2bde925 100644 --- a/src/ship/items/tasks.rs +++ b/src/ship/items/tasks.rs @@ -508,3 +508,27 @@ where Ok((transaction, item)) }) } + +pub fn floor_item_limit_reached<'a, EG> ( + item_state: &'a ItemState, + entity_gateway: &'a mut EG, + character: &'a CharacterEntity, + item_id: &'a ClientItemId, + map_area: MapArea +) -> BoxFuture<'a, Result<(), anyhow::Error>> +where + EG: EntityGateway + 'static, + EG::Transaction<'a>: Clone, +{ + entity_gateway.with_transaction(move |transaction| async move { + let item_state_proxy = ItemStateProxy::new(item_state.clone()); + let((item_state_proxy, transaction), result) = ItemStateAction::default() + .act(actions::take_item_from_floor(character.id, *item_id)) + .act(actions::delete_item_from_floor(map_area)) + .commit((item_state_proxy, transaction)) + .await?; + + item_state_proxy.commit().await; + Ok((transaction, result)) + }) +} diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs index f4e4d69..f380d14 100644 --- a/src/ship/packet/handler/message.rs +++ b/src/ship/packet/handler/message.rs @@ -10,7 +10,7 @@ use crate::ship::location::{ClientLocation, ClientLocationError}; use crate::ship::items::ClientItemId; use crate::ship::packet::builder; use crate::ship::items::state::ItemState; -use crate::ship::items::tasks::{drop_item, drop_partial_item, drop_meseta, equip_item, unequip_item, sort_inventory, use_item, feed_mag, sell_item, take_meseta}; +use crate::ship::items::tasks::{drop_item, drop_partial_item, drop_meseta, equip_item, unequip_item, sort_inventory, use_item, feed_mag, sell_item, take_meseta, floor_item_limit_reached}; pub async fn request_exp(id: ClientId, request_exp: RequestExp, @@ -500,3 +500,28 @@ where })}).await??; Ok(Vec::new()) // TODO: send the packet to other clients } + +pub async fn floor_item_limit_deletion (id: ClientId, + floor_item_limit_delete: FloorItemLimitItemDeletion, + entity_gateway: &mut EG, + client_location: &ClientLocation, + clients: &Clients, + rooms: &Rooms, + item_state: &mut ItemState) + -> Result, anyhow::Error> +where + EG: EntityGateway + Clone + 'static, +{ + let room_id = client_location.get_room(id).await.map_err(|err| -> ClientLocationError { err.into() })?; + let map_area = rooms.with(room_id, |room| Box::pin(async move { + room.map_areas.get_area_map(floor_item_limit_delete.map_area) + })).await??; + + clients.with(id, |client| { + let mut entity_gateway = entity_gateway.clone(); + let item_state = item_state.clone(); + Box::pin(async move { + floor_item_limit_reached(&item_state, &mut entity_gateway, &client.character, &ClientItemId(floor_item_limit_delete.item_id), map_area).await + })}).await??; + Ok(Vec::new()) +} diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 8a1c6fa..39e1075 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -575,6 +575,10 @@ impl ShipServerState { GameMessage::PlayerSoldItem(player_sold_item) => { handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &self.clients, &mut self.item_state).await? }, + GameMessage::FloorItemLimitItemDeletion(floor_item_limit_delete) => { + let block = self.blocks.get_from_client(id, &self.clients).await?; + handler::message::floor_item_limit_deletion(id, floor_item_limit_delete, &mut self.entity_gateway, &block.client_location, &self.clients, &block.rooms, &mut self.item_state).await? + }, _ => { let cmsg = msg.clone(); let block = self.blocks.get_from_client(id, &self.clients).await?; diff --git a/tests/test_item_pickup.rs b/tests/test_item_pickup.rs index 820e167..394cc3a 100644 --- a/tests/test_item_pickup.rs +++ b/tests/test_item_pickup.rs @@ -262,6 +262,7 @@ async fn test_pick_up_meseta_when_inventory_full() { room: 0, x: 0.0, z: 0.0, + amount: 23, })))).await.unwrap(); ship.handle(ClientId(2), RecvShipPacket::Message(Message::new(GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem { @@ -486,6 +487,7 @@ async fn test_can_not_drop_more_meseta_than_is_held() { room: 0, x: 0.0, z: 0.0, + amount: 301, })))).await.unwrap(); let split_attempt = ship.handle(ClientId(1), RecvShipPacket::Message(Message::new(GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem { @@ -604,6 +606,7 @@ async fn test_can_not_pick_up_meseta_when_full() { room: 0, x: 0.0, z: 0.0, + amount: 23, })))).await.unwrap(); ship.handle(ClientId(2), RecvShipPacket::Message(Message::new(GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem { @@ -658,6 +661,7 @@ async fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() { room: 0, x: 0.0, z: 0.0, + amount: 23, })))).await.unwrap(); ship.handle(ClientId(2), RecvShipPacket::Message(Message::new(GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem { @@ -722,6 +726,7 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() { room: 0, x: 0.0, z: 0.0, + amount: 2, })))).await.unwrap(); ship.handle(ClientId(1), RecvShipPacket::Message(Message::new(GameMessage::PlayerNoLongerHasItem(PlayerNoLongerHasItem {