From 13c6592438b782a70cf0aaf2cd36bc2b98864b7b Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 29 Jan 2023 23:05:42 -0700 Subject: [PATCH] you can use techs now wow --- src/entity/character.rs | 8 ++-- src/ship/items/apply_item.rs | 27 +++++++++-- tests/test_item_use.rs | 87 ++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 8 deletions(-) diff --git a/src/entity/character.rs b/src/entity/character.rs index 8b6c4e8..ddf892a 100644 --- a/src/entity/character.rs +++ b/src/entity/character.rs @@ -157,7 +157,7 @@ pub struct CharacterAppearance { } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct TechLevel(pub u8); #[derive(Clone, Debug, Default)] @@ -167,16 +167,14 @@ pub struct CharacterTechniques { impl CharacterTechniques { pub fn set_tech(&mut self, tech: Technique, level: TechLevel) { - self.techs.insert(tech, TechLevel(level.0 - 1)); + self.techs.insert(tech, TechLevel(level.0)); } - // from_bytes - pub fn as_bytes(&self) -> [u8; 20] { self.techs.iter() .fold([0xFF; 20], |mut techlist, (tech, level)| { let index = tech.as_value(); - techlist[index as usize] = level.0; + techlist[index as usize] = level.0 - 1; techlist }) } diff --git a/src/ship/items/apply_item.rs b/src/ship/items/apply_item.rs index bd01ecf..c418645 100644 --- a/src/ship/items/apply_item.rs +++ b/src/ship/items/apply_item.rs @@ -1,12 +1,14 @@ use std::convert::TryInto; use futures::future::join_all; use thiserror::Error; +use anyhow::Context; use rand::SeedableRng; use rand::distributions::{WeightedIndex, Distribution}; use crate::entity::gateway::{EntityGateway, GatewayError}; -use crate::entity::character::CharacterEntity; +use crate::entity::character::{CharacterEntity, TechLevel}; use crate::entity::item::mag::{MagCell, MagCellError}; use crate::entity::item::tool::{Tool, ToolType}; +use crate::entity::item::tech::{TechniqueDisk, Technique}; use crate::entity::item::{ItemDetail, ItemEntityId}; use crate::ship::items::state::{ItemStateProxy, ItemStateError}; use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail}; @@ -18,7 +20,7 @@ pub enum ApplyItemError { NoCharacter, #[error("item not equipped")] ItemNotEquipped, - #[error("invalid item")] + #[error("could not use item invalid item")] InvalidItem, #[error("gateway error {0}")] GatewayError(#[from] GatewayError), @@ -307,6 +309,21 @@ where } +async fn apply_tech<'a, EG>(item_state: &mut ItemStateProxy, + entity_gateway: &mut EG, + character: &mut CharacterEntity, + _entity_id: ItemEntityId, + tech: TechniqueDisk) + -> Result, anyhow::Error> +where + EG: EntityGateway + ?Sized, +{ + // TODO: make sure the class can learn that specific tech + character.techs.set_tech(tech.tech, TechLevel(tech.level as u8)); + entity_gateway.save_character(character).await.unwrap(); + Ok(vec![ApplyItemAction::UpdateCharacter(Box::new(character.clone()))]) + +} pub async fn apply_item<'a, EG>(item_state: &mut ItemStateProxy, entity_gateway: &mut EG, @@ -320,7 +337,11 @@ where InventoryItemDetail::Individual(individual_item) => { match individual_item.item { ItemDetail::Tool(tool) => apply_tool(item_state, entity_gateway, character, individual_item.entity_id, tool.tool).await, - _ => Err(ApplyItemError::InvalidItem.into()) + ItemDetail::TechniqueDisk(tech) => apply_tech(item_state, entity_gateway, character, individual_item.entity_id, tech).await, + _ => Err(anyhow::Error::from(ApplyItemError::InvalidItem)) + .with_context(|| { + format!("item {:?}", individual_item) + }) } }, InventoryItemDetail::Stacked(stacked_item) => { diff --git a/tests/test_item_use.rs b/tests/test_item_use.rs index 2289822..f9a9b67 100644 --- a/tests/test_item_use.rs +++ b/tests/test_item_use.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}; +use elseware::entity::character::TechLevel; //use elseware::ship::items::{ClientItemId, ActiveItemEntityId, HeldItemType, FloorItemType}; use libpso::packet::ship::*; @@ -304,6 +305,92 @@ async fn test_jackolantern() { } } + +#[async_std::test] +async fn test_use_barta_1() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await; + + /* + let mut p1_inv = Vec::new(); + for tool in vec![item::tool::ToolType::PowerMaterial, item::tool::ToolType::].into_iter() { + let mut item = Vec::new(); + for _ in 0..5usize { + item.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Tool( + item::tool::Tool { + tool: tool + } + ), + }).await.unwrap()); + } + p1_inv.push(item::InventoryItemEntity::Stacked(item)); +}*/ + let inv = vec![ + entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::TechniqueDisk( + item::tech::TechniqueDisk { + tech: item::tech::Technique::Foie, + level: 3, + } + ) + } + ).await.unwrap(), + entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::TechniqueDisk( + item::tech::TechniqueDisk { + tech: item::tech::Technique::Barta, + level: 4, + } + ) + } + ).await.unwrap(), + entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::TechniqueDisk( + item::tech::TechniqueDisk { + tech: item::tech::Technique::Zonde, + level: 5, + } + ) + } + ).await.unwrap() + ]; + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(inv)).await.unwrap(); + + let mut ship = Box::new(ShipServerState::builder() + .gateway(entity_gateway.clone()) + .build()); + log_in_char(&mut ship, ClientId(1), "a1", "a").await; + join_lobby(&mut ship, ClientId(1)).await; + create_room(&mut ship, ClientId(1), "room", "").await; + + ship.handle(ClientId(1), RecvShipPacket::Message(Message::new(GameMessage::PlayerUseItem(PlayerUseItem { + client: 0, + target: 0, + item_id: 0x10000, + })))).await.unwrap(); + + ship.handle(ClientId(1), RecvShipPacket::Message(Message::new(GameMessage::PlayerUseItem(PlayerUseItem { + client: 0, + target: 0, + item_id: 0x10002, + })))).await.unwrap(); + + let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let char = characters[0].as_ref().unwrap(); + + assert_eq!(char.techs.techs.len(), 2); + assert_eq!(char.techs.techs.get(&item::tech::Technique::Foie).unwrap(), &TechLevel(3)); + assert_eq!(char.techs.techs.get(&item::tech::Technique::Zonde).unwrap(), &TechLevel(5)); + assert!(char.techs.techs.get(&item::tech::Technique::Barta).is_none()); +} + // TODO: tests for ALL ITEMS WOW /*