From 50c5699f3413b9f636751187b66d992b2fb81789 Mon Sep 17 00:00:00 2001 From: jake Date: Wed, 2 Sep 2020 22:03:45 -0600 Subject: [PATCH] handle mags changing owners --- src/entity/gateway/entitygateway.rs | 4 ++ src/entity/gateway/inmemory.rs | 41 ++++++++++++------ src/entity/item/mag.rs | 9 ++-- src/ship/items/inventory.rs | 9 +++- src/ship/items/manager.rs | 5 ++- tests/test_mags.rs | 66 +++++++++++++++++++++++++++++ 6 files changed, 116 insertions(+), 18 deletions(-) diff --git a/src/entity/gateway/entitygateway.rs b/src/entity/gateway/entitygateway.rs index e9e0130..168c870 100644 --- a/src/entity/gateway/entitygateway.rs +++ b/src/entity/gateway/entitygateway.rs @@ -64,6 +64,10 @@ pub trait EntityGateway: Send + Sync + Clone { unimplemented!(); } + async fn change_mag_owner(&mut self, _mag_item_id: &ItemEntityId, _character: &CharacterEntity) { + unimplemented!(); + } + async fn get_items_by_character(&self, _char: &CharacterEntity) -> Vec { unimplemented!(); } diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 54ad825..f263ece 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -13,7 +13,7 @@ pub struct InMemoryGateway { user_settings: Arc>>, characters: Arc>>, items: Arc>>, - mag_feedings: Arc>>>, + mag_modifiers: Arc>>>, } impl InMemoryGateway { @@ -23,7 +23,7 @@ impl InMemoryGateway { user_settings: Arc::new(Mutex::new(BTreeMap::new())), characters: Arc::new(Mutex::new(BTreeMap::new())), items: Arc::new(Mutex::new(BTreeMap::new())), - mag_feedings: Arc::new(Mutex::new(BTreeMap::new())), + mag_modifiers: Arc::new(Mutex::new(BTreeMap::new())), } } } @@ -168,10 +168,19 @@ impl EntityGateway for InMemoryGateway { } async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) { - self.mag_feedings.lock().unwrap() + self.mag_modifiers.lock().unwrap() .entry(*mag_item_id) .or_insert(Vec::new()) - .push(*tool_item_id); + .push(mag::MagModifier::FeedMag { + food: *tool_item_id + }); + } + + async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) { + self.mag_modifiers.lock().unwrap() + .entry(*mag_item_id) + .or_insert(Vec::new()) + .push(mag::MagModifier::OwnerChange(character.char_class, character.section_id)); } async fn get_items_by_character(&self, character: &CharacterEntity) -> Vec { @@ -191,14 +200,22 @@ impl EntityGateway for InMemoryGateway { .map(|mut item| { item.item = match item.item { ItemDetail::Mag(mut mag) => { - self.mag_feedings.lock().unwrap().get(&item.id).map(|mag_feedings| { - for mag_feed_id in mag_feedings.iter() { - items.get(&mag_feed_id).map(|mag_feed| { - match mag_feed.item { - ItemDetail::Tool(mag_feed) => mag.feed(mag_feed.tool), - _ => {} - } - }); + self.mag_modifiers.lock().unwrap().get(&item.id).map(|mag_modifiers| { + for mag_modifier in mag_modifiers.iter() { + match mag_modifier { + mag::MagModifier::FeedMag {food} => { + items.get(&food).map(|mag_feed| { + match mag_feed.item { + ItemDetail::Tool(mag_feed) => mag.feed(mag_feed.tool), + _ => {} + } + }); + }, + mag::MagModifier::OwnerChange(class, section_id) => { + mag.change_owner(*class, *section_id) + }, + _ => {} + } } }); ItemDetail::Mag(mag) diff --git a/src/entity/item/mag.rs b/src/entity/item/mag.rs index 442bdc2..55b2f00 100644 --- a/src/entity/item/mag.rs +++ b/src/entity/item/mag.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use serde::{Serialize, Deserialize}; use crate::entity::item::tool::ToolType; use crate::entity::character::{CharacterClass, SectionID}; +use crate::entity::item::ItemEntityId; use std::io::Read; use std::cmp::Ordering::{Less, Greater, Equal}; @@ -449,10 +450,10 @@ impl MagAttributeOrdering { #[derive(Debug, Clone, PartialEq)] pub enum MagModifier { FeedMag{ - food: ToolType, + food: ItemEntityId, }, BankMag, // when putting a mag in the bank it truncates the values which has applications when raising degenerate mags - MagCell(ToolType), + MagCell(ItemEntityId), OwnerChange(CharacterClass, SectionID) } @@ -478,8 +479,8 @@ pub struct Mag { photon_blast: [Option; 3], pub color: u8, //modifiers: Vec, - class: CharacterClass, - id: SectionID, + pub class: CharacterClass, + pub id: SectionID, } diff --git a/src/ship/items/inventory.rs b/src/ship/items/inventory.rs index 044b6e2..024a2ca 100644 --- a/src/ship/items/inventory.rs +++ b/src/ship/items/inventory.rs @@ -22,7 +22,14 @@ pub struct IndividualInventoryItem { } impl IndividualInventoryItem { - pub fn mag(&mut self) -> Option<&mut Mag> { + pub fn mag(&self) -> Option<&Mag> { + match self.item { + ItemDetail::Mag(ref mag) => Some(mag), + _ => None + } + } + + pub fn mag_mut(&mut self) -> Option<&mut Mag> { match self.item { ItemDetail::Mag(ref mut mag) => Some(mag), _ => None diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index 9c3c83b..276e433 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -261,6 +261,9 @@ impl ItemManager { equipped: false, } ).await; + if let Some(_) = new_inventory_item.mag() { + entity_gateway.change_mag_owner(&new_inventory_item.entity_id, character).await; + } }, None => { return Err(ItemManagerError::CouldNotAddToInventory(item_id)); @@ -615,7 +618,7 @@ impl ItemManager { .individual() .ok_or(ItemManagerError::WrongItemType(mag_id))?; let mag = individual_item - .mag() + .mag_mut() .ok_or(ItemManagerError::WrongItemType(mag_id))?; let consumed_tool_type = match &consumed_tool { diff --git a/tests/test_mags.rs b/tests/test_mags.rs index b9bf032..099455a 100644 --- a/tests/test_mags.rs +++ b/tests/test_mags.rs @@ -2,6 +2,7 @@ use elseware::common::serverstate::{ClientId, ServerState}; use elseware::entity::gateway::{EntityGateway, InMemoryGateway}; use elseware::entity::item; use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket}; +use elseware::entity::character::{CharacterClass, SectionID}; use libpso::packet::ship::*; use libpso::packet::messages::*; @@ -72,3 +73,68 @@ async fn test_mag_feed() { _ => panic!() } } + +#[async_std::test] +async fn test_mag_change_owner() { + let mut entity_gateway = InMemoryGateway::new(); + + let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await; + char1.char_class = CharacterClass::RAmarl; + char1.section_id = SectionID::Redria; + entity_gateway.save_character(&char1).await; + char2.char_class = CharacterClass::FOmarl; + char2.section_id = SectionID::Whitill; + entity_gateway.save_character(&char2).await; + + entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Mag( + item::mag::Mag::baby_mag(0) + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + slot: 0, + equipped: true, + } + }).await; + + let mut ship = ShipServerState::builder() + .gateway(entity_gateway.clone()) + .build(); + log_in_char(&mut ship, ClientId(1), "a1", "a").await; + log_in_char(&mut ship, ClientId(2), "a2", "a").await; + join_lobby(&mut ship, ClientId(1)).await; + join_lobby(&mut ship, ClientId(2)).await; + create_room(&mut ship, ClientId(1), "room", "").await; + join_room(&mut ship, ClientId(2), 0).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerDropItem(PlayerDropItem { + client: 0, + target: 0, + unknown1: 0, + map_area: 0, + item_id: 0x10000, + x: 0.0, + y: 0.0, + z: 0.0, + })))).await.unwrap().for_each(drop); + + ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem { + client: 0, + target: 0, + item_id: 0x10000, + map_area: 0, + unknown: [0; 3] + })))).await.unwrap().for_each(drop); + + let p2_items = entity_gateway.get_items_by_character(&char2).await; + let mag = p2_items.get(0).unwrap(); + match &mag.item { + item::ItemDetail::Mag(mag) => { + assert!(mag.class == CharacterClass::FOmarl); + assert!(mag.id == SectionID::Whitill); + }, + _ => panic!() + } +}