From 10aca8c7ec2041e3a2870440c15c31efb0c1d362 Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 20 Apr 2021 03:04:54 +0000 Subject: [PATCH 01/34] wow i should have pushed much smaller chunks more often oops. shop selling added, shop buying quantity bug fixed(?) added lots of todos --- src/bin/main.rs | 19 ++- src/entity/gateway/postgres/models.rs | 3 + src/entity/item/armor.rs | 72 ++++++++- src/entity/item/esweapon.rs | 5 + src/entity/item/mag.rs | 47 ++++++ src/entity/item/mod.rs | 2 + src/entity/item/shield.rs | 150 +++++++++++++++++++ src/entity/item/tool.rs | 170 ++++++++++++++++++++++ src/entity/item/unit.rs | 62 ++++++++ src/entity/item/weapon.rs | 66 ++++++++- src/ship/items/inventory.rs | 60 +++++++- src/ship/items/manager.rs | 48 +++++- src/ship/packet/handler/direct_message.rs | 5 +- src/ship/packet/handler/message.rs | 28 +++- src/ship/ship.rs | 3 + src/ship/shops/armor.rs | 14 ++ src/ship/shops/tool.rs | 10 ++ src/ship/shops/weapon.rs | 22 ++- 18 files changed, 767 insertions(+), 19 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index a9ed329..ee9aa8c 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -350,6 +350,23 @@ fn main() { } } ).await.unwrap(); + let item14 = entity_gateway.create_item( + NewItemEntity { + item: ItemDetail::Weapon( + item::weapon::Weapon { + weapon: item::weapon::WeaponType::Vulcan, + grind: 5, + special: Some(item::weapon::WeaponSpecial::Charge), + attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}), + Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}), + Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Native, value: 100}),], + tekked: true, + } + ), + location: ItemLocation::Inventory { + character_id: character.id, + } + }).await.unwrap(); let equipped = item::EquippedEntity { weapon: Some(item2_w.id), @@ -360,7 +377,7 @@ fn main() { }; entity_gateway.set_character_equips(&character.id, &equipped).await.unwrap(); - let inventory = item::InventoryEntity::new(vec![item0, item1, item2_w, item3, item4, item5_m, item6, item7_a, item8_s, item9_u0, item10_u1, item11_u2, item12_u3, item13]); + let inventory = item::InventoryEntity::new(vec![item0, item1, item2_w, item3, item4, item5_m, item6, item7_a, item8_s, item9_u0, item10_u1, item11_u2, item12_u3, item13, item14]); entity_gateway.set_character_inventory(&character.id, &inventory).await.unwrap(); entity_gateway.set_character_bank(&character.id, &item::BankEntity::default(), item::BankName("".into())).await.unwrap(); } diff --git a/src/entity/gateway/postgres/models.rs b/src/entity/gateway/postgres/models.rs index 02bd750..5f90986 100644 --- a/src/entity/gateway/postgres/models.rs +++ b/src/entity/gateway/postgres/models.rs @@ -597,6 +597,7 @@ pub enum PgItemLocationDetail { mag: u32, }, Shop, + SoldToShop, } impl From for PgItemLocationDetail { @@ -609,6 +610,7 @@ impl From for PgItemLocationDetail { ItemLocation::Consumed => PgItemLocationDetail::Consumed, ItemLocation::FedToMag{mag} => PgItemLocationDetail::FedToMag{mag: mag.0}, ItemLocation::Shop => PgItemLocationDetail::Shop, + ItemLocation::SoldToShop => PgItemLocationDetail::SoldToShop, } } } @@ -623,6 +625,7 @@ impl From for ItemLocation { PgItemLocationDetail::Consumed => ItemLocation::Consumed, PgItemLocationDetail::FedToMag{mag} => ItemLocation::FedToMag{mag: ItemEntityId(mag)}, PgItemLocationDetail::Shop => ItemLocation::Shop, + PgItemLocationDetail::SoldToShop => ItemLocation::SoldToShop, } } } diff --git a/src/entity/item/armor.rs b/src/entity/item/armor.rs index 6d2489d..4d7291e 100644 --- a/src/entity/item/armor.rs +++ b/src/entity/item/armor.rs @@ -297,7 +297,7 @@ pub enum ArmorModifier { } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] pub struct Armor { pub armor: ArmorType, pub dfp: u8, @@ -329,4 +329,74 @@ impl Armor { Err(ItemParseError::InvalidArmorBytes) // TODO: error handling if wrong bytes are given } } + + pub fn is_rare_item(self) -> bool { + match self.armor { + ArmorType::HunterField => true, + ArmorType::RangerField => true, + ArmorType::ForceField => true, + ArmorType::RevivalGarment => true, + ArmorType::SpiritGarment => true, + ArmorType::StinkFrame => true, + ArmorType::DPartsVer101 => true, + ArmorType::DPartsVer210 => true, + ArmorType::ParasiteWearDeRol => true, + ArmorType::ParasiteWearNelgal => true, + ArmorType::ParasiteWearVajulla => true, + ArmorType::SensePlate => true, + ArmorType::GravitonPlate => true, + ArmorType::AttributePlate => true, + ArmorType::FlowensFrame => true, + ArmorType::CustomFrameVerOo => true, + ArmorType::DbsArmor => true, + ArmorType::GuardWave => true, + ArmorType::DfField => true, + ArmorType::LuminousField => true, + ArmorType::ChuChuFever => true, + ArmorType::LoveHeart => true, + ArmorType::FlameGarment => true, + ArmorType::VirusArmorLafuteria => true, + ArmorType::BrightnessCircle => true, + ArmorType::AuraField => true, + ArmorType::ElectroFrame => true, + ArmorType::SacredCloth => true, + ArmorType::SmokingPlate => true, + ArmorType::StarCuirass => true, + ArmorType::BlackHoundCuirass => true, + ArmorType::MorningPrayer => true, + ArmorType::BlackOdoshiDomaru => true, + ArmorType::RedOdoshiDomaru => true, + ArmorType::BlackOdoshiRedNimaidou => true, + ArmorType::BlueOdoshiVioletNimaidou => true, + ArmorType::DirtyLifejacket => true, + ArmorType::KroesSweater => true, + ArmorType::WeddingDress => true, + ArmorType::SonicteamArmor => true, + ArmorType::RedCoat => true, + ArmorType::Thirteen => true, + ArmorType::MotherGarb => true, + ArmorType::MotherGarbPlus => true, + ArmorType::DressPlate => true, + ArmorType::Sweetheart => true, + ArmorType::IgnitionCloak => true, + ArmorType::CongealCloak => true, + ArmorType::TempestCloak => true, + ArmorType::CursedCloak => true, + ArmorType::SelectCloak => true, + ArmorType::SpiritCuirass => true, + ArmorType::RevivalCuriass => true, + ArmorType::AllianceUniform => true, + ArmorType::OfficerUniform => true, + ArmorType::CommanderUniform => true, + ArmorType::CrimsonCoat => true, + ArmorType::InfantryGear => true, + ArmorType::LieutenantGear => true, + ArmorType::InfantryMantle => true, + ArmorType::LieutenantMantle => true, + ArmorType::UnionField => true, + ArmorType::SamuraiArmor => true, + ArmorType::StealthSuit => true, + _ => false, + } + } } diff --git a/src/entity/item/esweapon.rs b/src/entity/item/esweapon.rs index 908b026..3a88ccd 100644 --- a/src/entity/item/esweapon.rs +++ b/src/entity/item/esweapon.rs @@ -253,6 +253,11 @@ impl ESWeapon { name, } } + + // TODO: this isn't even needed. all sranks are rare and only sell for 10? meseta in the shop + pub fn is_rare_item(self) -> bool { + true + } } #[cfg(test)] diff --git a/src/entity/item/mag.rs b/src/entity/item/mag.rs index 4f36983..b5aebd6 100644 --- a/src/entity/item/mag.rs +++ b/src/entity/item/mag.rs @@ -1098,6 +1098,53 @@ impl Mag { MagCell::LibertaKit => MagType::Agastya, } } + + // TODO: is this even needed? mags are not shop sellable...yet + pub fn is_rare_item(self) -> bool { + match self.mag { + MagType::Pitri => true, + MagType::Soniti => true, + MagType::Preta => true, + MagType::Churel => true, + MagType::Robochao => true, + MagType::OpaOpa => true, + MagType::Pian => true, + MagType::Chao => true, + MagType::ChuChu => true, + MagType::KapuKapu => true, + MagType::AngelsWing => true, + MagType::DevilsWing => true, + MagType::Elenor => true, + MagType::MarkIII => true, + MagType::MasterSystem => true, + MagType::Genesis => true, + MagType::SegaSaturn => true, + MagType::Dreamcast => true, + MagType::Hamburger => true, + MagType::PanzersTail => true, + MagType::DevilsTail => true, + MagType::Deva => true, + MagType::Rati => true, + MagType::Savitri => true, + MagType::Rukmin => true, + MagType::Pushan => true, + MagType::Diwari => true, + MagType::Sato => true, + MagType::Bhima => true, + MagType::Nidra => true, + MagType::GeungSi => true, + MagType::Tellusis => true, + MagType::StrikerUnit => true, + MagType::Pioneer => true, + MagType::Puyo => true, + MagType::Moro => true, + MagType::Rappy => true, + MagType::Yahoo => true, + MagType::GaelGiel => true, + MagType::Agastya => true, + _ => false, + } + } } diff --git a/src/entity/item/mod.rs b/src/entity/item/mod.rs index 9959f54..9a0a0c8 100644 --- a/src/entity/item/mod.rs +++ b/src/entity/item/mod.rs @@ -12,6 +12,7 @@ use serde::{Serialize, Deserialize}; use crate::entity::character::CharacterEntityId; use crate::ship::map::MapArea; use crate::ship::drops::ItemDropType; +use crate::ship::shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem}; #[derive(PartialEq, Copy, Clone, Debug, Hash, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct ItemEntityId(pub u32); @@ -47,6 +48,7 @@ pub enum ItemLocation { mag: ItemEntityId, }, Shop, + SoldToShop, /*Destroyed { // marks an item that has been consumed in some way }, diff --git a/src/entity/item/shield.rs b/src/entity/item/shield.rs index 5784fd4..2f494cd 100644 --- a/src/entity/item/shield.rs +++ b/src/entity/item/shield.rs @@ -548,4 +548,154 @@ impl Shield { Err(ItemParseError::InvalidShieldBytes) // TODO: error handling if wrong bytes are given } } + + pub fn is_rare_item(self) -> bool { + match self.shield { + ShieldType::InvisibleGuard => true, + ShieldType::SacredGuard => true, + ShieldType::SPartsVer116 => true, + ShieldType::SPartsVer201 => true, + ShieldType::LightRelief => true, + ShieldType::ShieldOfDelsaber => true, + ShieldType::ForceWall => true, + ShieldType::RangerWall => true, + ShieldType::HunterWall => true, + ShieldType::AttributeWall => true, + ShieldType::SecretGear => true, + ShieldType::CombatGear => true, + ShieldType::ProtoRegeneGear => true, + ShieldType::RegenerateGear => true, + ShieldType::RegeneGearAdv => true, + ShieldType::FlowensShield => true, + ShieldType::CustomBarrierVerOo => true, + ShieldType::DbsShield => true, + ShieldType::RedRing => true, + ShieldType::TripolicShield => true, + ShieldType::StandstillShield => true, + ShieldType::SafetyHeart => true, + ShieldType::KasamiBracer => true, + ShieldType::GodsShieldSuzaku => true, + ShieldType::GodsShieldGenbu => true, + ShieldType::GodsShieldByakko => true, + ShieldType::GodsShieldSeiryu => true, + ShieldType::HuntersShell => true, + ShieldType::RicosGlasses => true, + ShieldType::RicosEarring => true, + ShieldType::BlueRing => true, + ShieldType::Barrier2 => true, + ShieldType::SecureFeet => true, + ShieldType::Barrier3 => true, + ShieldType::Barrier4 => true, + ShieldType::Barrier5 => true, + ShieldType::Barrier6 => true, + ShieldType::RestaMerge => true, + ShieldType::AntiMerge => true, + ShieldType::ShiftaMerge => true, + ShieldType::DebandMerge => true, + ShieldType::FoieMerge => true, + ShieldType::GifoieMerge => true, + ShieldType::RafoieMerge => true, + ShieldType::RedMerge => true, + ShieldType::BartaMerge => true, + ShieldType::GibartaMerge => true, + ShieldType::RabartaMerge => true, + ShieldType::BlueMerge => true, + ShieldType::ZondeMerge => true, + ShieldType::GizondeMerge => true, + ShieldType::RazondeMerge => true, + ShieldType::YellowMerge => true, + ShieldType::RecoveryBarrier => true, + ShieldType::AssistBarrier => true, + ShieldType::RedBarrier => true, + ShieldType::BlueBarrier => true, + ShieldType::YellowBarrier => true, + ShieldType::WeaponsGoldShield => true, + ShieldType::BlackGear => true, + ShieldType::WorksGuard => true, + ShieldType::RagolRing => true, + ShieldType::BlueRing2 => true, + ShieldType::BlueRing3 => true, + ShieldType::BlueRing4 => true, + ShieldType::BlueRing5 => true, + ShieldType::BlueRing6 => true, + ShieldType::BlueRing7 => true, + ShieldType::BlueRing8 => true, + ShieldType::BlueRing9 => true, + ShieldType::GreenRing => true, + ShieldType::GreenRing2 => true, + ShieldType::GreenRing3 => true, + ShieldType::GreenRing4 => true, + ShieldType::GreenRing5 => true, + ShieldType::GreenRing6 => true, + ShieldType::GreenRing7 => true, + ShieldType::GreenRing8 => true, + ShieldType::YellowRing => true, + ShieldType::YellowRing2 => true, + ShieldType::YellowRing3 => true, + ShieldType::YellowRing4 => true, + ShieldType::YellowRing5 => true, + ShieldType::YellowRing6 => true, + ShieldType::YellowRing7 => true, + ShieldType::YellowRing8 => true, + ShieldType::PurpleRing => true, + ShieldType::PurpleRing2 => true, + ShieldType::PurpleRing3 => true, + ShieldType::PurpleRing4 => true, + ShieldType::PurpleRing5 => true, + ShieldType::PurpleRing6 => true, + ShieldType::PurpleRing7 => true, + ShieldType::PurpleRing8 => true, + ShieldType::WhiteRing => true, + ShieldType::WhiteRing2 => true, + ShieldType::WhiteRing3 => true, + ShieldType::WhiteRing4 => true, + ShieldType::WhiteRing5 => true, + ShieldType::WhiteRing6 => true, + ShieldType::WhiteRing7 => true, + ShieldType::WhiteRing8 => true, + ShieldType::BlackRing => true, + ShieldType::BlackRing2 => true, + ShieldType::BlackRing3 => true, + ShieldType::BlackRing4 => true, + ShieldType::BlackRing5 => true, + ShieldType::BlackRing6 => true, + ShieldType::BlackRing7 => true, + ShieldType::BlackRing8 => true, + ShieldType::WeaponsSilverShield => true, + ShieldType::WeaponsCopperShield => true, + ShieldType::Gratia => true, + ShieldType::TripolicReflector => true, + ShieldType::StrikerPlus => true, + ShieldType::RegenerateGearBP => true, + ShieldType::Rupika => true, + ShieldType::YataMirror => true, + ShieldType::BunnyEars => true, + ShieldType::CatEars => true, + ShieldType::ThreeSeals => true, + ShieldType::GodsShieldKouryu => true, + ShieldType::DfShield => true, + ShieldType::FromTheDepths => true, + ShieldType::DeRolLeShield => true, + ShieldType::HoneycombReflector => true, + ShieldType::Epsiguard => true, + ShieldType::AngelRing => true, + ShieldType::UnionGuard => true, + ShieldType::UnionGuard2 => true, + ShieldType::UnionGuard3 => true, + ShieldType::UnionGuard4 => true, + ShieldType::StinkShield => true, + ShieldType::Unknownb => true, + ShieldType::Genpei => true, + ShieldType::Genpei2 => true, + ShieldType::Genpei3 => true, + ShieldType::Genpei4 => true, + ShieldType::Genpei5 => true, + ShieldType::Genpei6 => true, + ShieldType::Genpei7 => true, + ShieldType::Genpei8 => true, + ShieldType::Genpei9 => true, + ShieldType::Genpei10 => true, + _ => false, + } + } } diff --git a/src/entity/item/tool.rs b/src/entity/item/tool.rs index 054a922..b20845f 100644 --- a/src/entity/item/tool.rs +++ b/src/entity/item/tool.rs @@ -680,4 +680,174 @@ impl Tool { pub fn max_stack(&self) -> usize { self.tool.max_stack() } + + pub fn is_rare_item(self) -> bool { + match self.tool { + ToolType::CellOfMag502 => true, + ToolType::CellOfMag213 => true, + ToolType::PartsOfRobochao => true, + ToolType::HeartOfOpaOpa => true, + ToolType::HeartOfPian => true, + ToolType::HeartOfChao => true, + ToolType::SorcerersRightArm => true, + ToolType::SBeatsArms => true, + ToolType::PArmsArms => true, + ToolType::DelsabersRightArm => true, + ToolType::BringersRightArm => true, + ToolType::DelsabersLeftArm => true, + ToolType::SRedsArms => true, + ToolType::DragonsClaw => true, + ToolType::HildebearsHead => true, + ToolType::HildebluesHead => true, + ToolType::PartsOfBaranz => true, + ToolType::BelrasRightArm => true, + ToolType::GiGuesBody => true, + ToolType::SinowBerillsArms => true, + ToolType::GrassAssassinsArms => true, + ToolType::BoomasRightArm => true, + ToolType::GoboomasRightArm => true, + ToolType::GigoboomasRightArm => true, + ToolType::GalGryphonsWing => true, + ToolType::RappysWing => true, + ToolType::CladdingOfEpsilon => true, + ToolType::DeRolLeShell => true, + ToolType::BerillPhoton => true, + ToolType::ParasiticGeneFlow => true, + ToolType::MagicStoneIritista => true, + ToolType::BlueBlackStone => true, + ToolType::Syncesta => true, + ToolType::MagicWater => true, + ToolType::ParasiticCellTypeD => true, + ToolType::MagicRockHeartKey => true, + ToolType::MagicRockMoola => true, + ToolType::StarAmplifier => true, + ToolType::BookOfHitogata => true, + ToolType::HeartOfChuChu => true, + ToolType::PartsOfEggBlaster => true, + ToolType::HeartOfAngel => true, + ToolType::HeartOfDevil => true, + ToolType::KitOfHamburger => true, + ToolType::PanthersSpirit => true, + ToolType::KitOfMark3 => true, + ToolType::KitOfMasterSystem => true, + ToolType::KitOfGenesis => true, + ToolType::KitOfSegaSaturn => true, + ToolType::KitOfDreamcast => true, + ToolType::AmplifierOfResta => true, + ToolType::AmplifierOfAnti => true, + ToolType::AmplifierOfShifta => true, + ToolType::AmplifierOfDeband => true, + ToolType::AmplifierOfFoie => true, + ToolType::AmplifierOfGifoie => true, + ToolType::AmplifierOfRafoie => true, + ToolType::AmplifierOfBarta => true, + ToolType::AmplifierOfGibarta => true, + ToolType::AmplifierOfRabarta => true, + ToolType::AmplifierOfZonde => true, + ToolType::AmplifierOfGizonde => true, + ToolType::AmplifierOfRazonde => true, + ToolType::AmplifierOfRed => true, + ToolType::AmplifierOfBlue => true, + ToolType::AmplifierOfYellow => true, + ToolType::HeartOfKapuKapu => true, + ToolType::PhotonBooster => true, + ToolType::Addslot => true, + ToolType::PhotonDrop => true, + ToolType::PhotonSphere => true, + ToolType::PhotonCrystal => true, + ToolType::SecretTicket => true, + ToolType::PhotonTicket => true, + ToolType::BookOfKatana1 => true, + ToolType::BookOfKatana2 => true, + ToolType::BookOfKatana3 => true, + ToolType::WeaponsBronzeBadge => true, + ToolType::WeaponsSilverBadge => true, + ToolType::WeaponsGoldBadge => true, + ToolType::WeaponsCrystalBadge => true, + ToolType::WeaponsSteelBadge => true, + ToolType::WeaponsAluminumBadge => true, + ToolType::WeaponsLeatherBadge => true, + ToolType::WeaponsBoneBadge => true, + ToolType::LetterOfAppreciation => true, + ToolType::ItemTicket => true, + ToolType::ValentinesChocolate => true, + ToolType::NewYearsCard => true, + ToolType::ChristmasCard => true, + ToolType::BirthdayCard => true, + ToolType::ProofOfSonicTeam => true, + ToolType::SpecialEventTicket => true, + ToolType::FlowerBouquet => true, + ToolType::Cake => true, + ToolType::Accessories => true, + ToolType::MrNakasBusinessCard => true, + ToolType::Present => true, + ToolType::Chocolate => true, + ToolType::Candy => true, + ToolType::Cake2 => true, + ToolType::WeaponsSilverBadge2 => true, + ToolType::WeaponsGoldBadge2 => true, + ToolType::WeaponsCrystalBadge2 => true, + ToolType::WeaponsSteelBadge2 => true, + ToolType::WeaponsAluminumBadge2 => true, + ToolType::WeaponsLeatherBadge2 => true, + ToolType::WeaponsBoneBadge2 => true, + ToolType::Bouquet => true, + ToolType::Decoction => true, + ToolType::ChristmasPresent => true, + ToolType::EasterEgg => true, + ToolType::JackOLantern => true, + ToolType::DiskVol1WeddingMarch => true, + ToolType::DiskVol2DayLight => true, + ToolType::DiskVol3BurningRangers => true, + ToolType::DiskVol4OpenYourHeart => true, + ToolType::DiskVol5LiveLearn => true, + ToolType::DiskVol6Nights => true, + ToolType::DiskVol7EndingThemePianoVer => true, + ToolType::DiskVol8HeartToHeart => true, + ToolType::DiskVol9StrangeBlue => true, + ToolType::DiskVol10ReunionSystem => true, + ToolType::DiskVol11Pinnacles => true, + ToolType::DiskVol12FightInsideTheSpaceship => true, + ToolType::HuntersReport => true, + ToolType::HuntersReport2 => true, + ToolType::HuntersReport3 => true, + ToolType::HuntersReport4 => true, + ToolType::HuntersReport5 => true, + ToolType::Tablet => true, + ToolType::Unknown2 => true, + ToolType::DragonScale => true, + ToolType::HeavenStrikerCoat => true, + ToolType::PioneerParts => true, + ToolType::AmitiesMemo => true, + ToolType::HeartOfMorolian => true, + ToolType::RappysBeak => true, + ToolType::YahoosEngine => true, + ToolType::DPhotonCore => true, + ToolType::LibertaKit => true, + ToolType::CellOfMag0503 => true, + ToolType::CellOfMag0504 => true, + ToolType::CellOfMag0505 => true, + ToolType::CellOfMag0506 => true, + ToolType::CellOfMag0507 => true, + ToolType::TeamPoints500 => true, + ToolType::TeamPoints1000 => true, + ToolType::TeamPoints5000 => true, + ToolType::TeamPoints10000 => true, + _ => false, + } + } + + // TODO: do we actually need this function? + pub fn is_material(self) -> bool { + match self.tool { + ToolType::PowerMaterial => true, + ToolType::MindMaterial => true, + ToolType::EvadeMaterial => true, + ToolType::HpMaterial => true, + ToolType::TpMaterial => true, + ToolType::DefMaterial => true, + ToolType::LuckMaterial => true, + _ => false, + } + } } diff --git a/src/entity/item/unit.rs b/src/entity/item/unit.rs index df0b611..6e90bb0 100644 --- a/src/entity/item/unit.rs +++ b/src/entity/item/unit.rs @@ -384,4 +384,66 @@ impl Unit { Err(ItemParseError::InvalidUnitBytes) // TODO: error handling if wrong bytes are given } } + + pub fn is_rare_item(self) -> bool { + match self.unit { + UnitType::GodPower => true, + UnitType::GodMind => true, + UnitType::GodArm => true, + UnitType::GodLegs => true, + UnitType::GodHp => true, + UnitType::GodTp => true, + UnitType::GodBody => true, + UnitType::GodLuck => true, + UnitType::HeroAbility => true, + UnitType::GodAbility => true, + UnitType::AllResist => true, + UnitType::SuperResist => true, + UnitType::PerfectResist => true, + UnitType::HpRevival => true, + UnitType::TpRevival => true, + UnitType::PbAmplifier => true, + UnitType::PbGenerate => true, + UnitType::PbCreate => true, + UnitType::DevilTechnique => true, + UnitType::GodTechnique => true, + UnitType::DevilBattle => true, + UnitType::GodBattle => true, + UnitType::CurePoison => true, + UnitType::CureParalysis => true, + UnitType::CureSlow => true, + UnitType::CureConfuse => true, + UnitType::CureFreeze => true, + UnitType::CureShock => true, + UnitType::YasakaniMagatama => true, + UnitType::V101 => true, + UnitType::V501 => true, + UnitType::V502 => true, + UnitType::V801 => true, + UnitType::Limiter => true, + UnitType::Adept => true, + UnitType::SwordsmanLore => true, + UnitType::ProofOfSwordSaint => true, + UnitType::Smartlink => true, + UnitType::DivineProtection => true, + UnitType::HeavenlyBattle => true, + UnitType::HeavenlyPower => true, + UnitType::HeavenlyMind => true, + UnitType::HeavenlyArms => true, + UnitType::HeavenlyLegs => true, + UnitType::HeavenlyBody => true, + UnitType::HeavenlyLuck => true, + UnitType::HeavenlyAbility => true, + UnitType::CenturionAbility => true, + UnitType::FriendRing => true, + UnitType::HeavenlyHp => true, + UnitType::HeavenlyTp => true, + UnitType::HeavenlyResist => true, + UnitType::HeavenlyTechnique => true, + UnitType::HpRessurection => true, + UnitType::TpRessurection => true, + UnitType::PbIncrease => true, + _ => false, + } + } } diff --git a/src/entity/item/weapon.rs b/src/entity/item/weapon.rs index 6473dd8..5d20e71 100644 --- a/src/entity/item/weapon.rs +++ b/src/entity/item/weapon.rs @@ -1454,7 +1454,7 @@ pub enum WeaponModifier { }, } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] pub struct Weapon { pub weapon: WeaponType, pub special: Option, @@ -1584,6 +1584,70 @@ impl Weapon { Err(ItemParseError::InvalidWeaponBytes) // TODO: error handling if wrong bytes are given } } + + // TODO: invert this? ie: handgun, saber, dagger etc. => false, _ => true? + pub fn is_rare_item(self) -> bool { + match self.weapon { + WeaponType::Saber => false, + WeaponType::Brand => false, + WeaponType::Buster => false, + WeaponType::Pallasch => false, + WeaponType::Gladius => false, + WeaponType::Sword => false, + WeaponType::Gigush => false, + WeaponType::Breaker => false, + WeaponType::Claymore => false, + WeaponType::Calibur => false, + WeaponType::Dagger => false, + WeaponType::Knife => false, + WeaponType::Blade => false, + WeaponType::Edge => false, + WeaponType::Ripper => false, + WeaponType::Partisan => false, + WeaponType::Halbert => false, + WeaponType::Glaive => false, + WeaponType::Berdys => false, + WeaponType::Gungnir => false, + WeaponType::Slicer => false, + WeaponType::Spinner => false, + WeaponType::Cutter => false, + WeaponType::Sawcer => false, + WeaponType::Diska => false, + WeaponType::Handgun => false, + WeaponType::Autogun => false, + WeaponType::Lockgun => false, + WeaponType::Railgun => false, + WeaponType::Raygun => false, + WeaponType::Rifle => false, + WeaponType::Sniper => false, + WeaponType::Blaster => false, + WeaponType::Beam => false, + WeaponType::Laser => false, + WeaponType::Mechgun => false, + WeaponType::Assault => false, + WeaponType::Repeater => false, + WeaponType::Gatling => false, + WeaponType::Vulcan => false, + WeaponType::Shot => false, + WeaponType::Spread => false, + WeaponType::Cannon => false, + WeaponType::Launcher => false, + WeaponType::Arms => false, + WeaponType::Cane => false, + WeaponType::Stick => false, + WeaponType::Mace => false, + WeaponType::Club => false, + WeaponType::Rod => false, + WeaponType::Pole => false, + WeaponType::Pillar => false, + WeaponType::Striker => false, + WeaponType::Wand => false, + WeaponType::Staff => false, + WeaponType::Baton => false, + WeaponType::Scepter => false, + _ => true, + } + } } diff --git a/src/ship/items/inventory.rs b/src/ship/items/inventory.rs index 9589849..81bd733 100644 --- a/src/ship/items/inventory.rs +++ b/src/ship/items/inventory.rs @@ -3,11 +3,12 @@ use thiserror::Error; use libpso::character::character;//::InventoryItem; use crate::entity::character::CharacterEntityId; use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, ItemType, ItemLocation, InventoryEntity, InventoryItemEntity, EquippedEntity}; -use crate::entity::item::tool::Tool; +use crate::entity::item::tool::{Tool, ToolType}; use crate::entity::item::mag::Mag; use crate::entity::item::weapon::Weapon; use crate::ship::items::{ClientItemId, BankItem, BankItemHandle}; use crate::ship::items::floor::{IndividualFloorItem, StackedFloorItem}; +use crate::ship::shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem}; const INVENTORY_CAPACITY: usize = 30; @@ -220,6 +221,63 @@ impl InventoryItem { _ => None } } + + pub fn get_sell_price(&self) -> Option { + match self { + InventoryItem::Individual(individual_item) => { + match &individual_item.item { + // TODO: can wrapped items be sold? + ItemDetail::Weapon(w) => { + if !w.tekked { + return Some(1u32) + } + if w.is_rare_item() { + return Some(10u32) + } + // other item factors? + return Some((WeaponShopItem::weapon_from_item(w).price() / 8) as u32) + }, + ItemDetail::Armor(a) => { + if a.is_rare_item() { + return Some(10u32) + } + return Some((ArmorShopItem::armor_from_item(a).price() / 8) as u32) + }, + ItemDetail::Shield(s) => { + if s.is_rare_item() { + return Some(10u32) + } + return Some((ArmorShopItem::shield_from_item(s).price() / 8) as u32) + }, + ItemDetail::Unit(u) => { + if u.is_rare_item() { + return Some(10u32) + } + return Some((ArmorShopItem::unit_from_item(u).price() / 8) as u32) + }, + ItemDetail::Tool(t) => { + if t.is_rare_item() { // TODO: photon drop/sphere etc + return Some(10u32) + } + return Some((ToolShopItem::tool_from_item(t).price() / 8) as u32) + }, + ItemDetail::TechniqueDisk(d) => { // TODO: are all techs the same? + return Some((ToolShopItem::tech_from_item(d).price() / 8) as u32) + }, + ItemDetail::Mag(_m) => { //TODO: error. mags are not sellable + return None + }, + ItemDetail::ESWeapon(_e) => { + return Some(10u32) // TODO: check price + }, + } + }, + // the number of stacked items sold is handled by the caller. this is just the price of 1 + InventoryItem::Stacked(stacked_item) => { + return Some((ToolShopItem::tool_from_item(&stacked_item.tool).price() / 8) as u32) + }, + } + } } diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index 441c85b..65cede0 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -1,5 +1,6 @@ use crate::ship::items::ClientItemId; -use std::collections::HashMap; +use std::collections::{HashMap, BTreeMap}; +use std::cmp::Ordering; use thiserror::Error; use crate::entity::gateway::EntityGateway; use crate::entity::character::{CharacterEntity, CharacterEntityId, TechLevel}; @@ -55,6 +56,8 @@ pub enum ItemManagerError { NoArmorEquipped, GatewayError(#[from] crate::entity::gateway::GatewayError), StackedItemError(Vec), + ItemNotSellable, // TODO: capture what item was attempted to be sold + WalletFull, } pub struct ItemManager { @@ -844,6 +847,49 @@ impl ItemManager { Ok(inventory_item) } + pub async fn player_sells_item(&mut self, + entity_gateway: &mut EG, + character: &mut CharacterEntity, + item_id: ClientItemId, + amount: usize) + -> Result<(), anyhow::Error> { + let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?; + let sold_item_handle = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?; + if let Some(item_sold) = sold_item_handle.item() { + if let Some(unit_price) = item_sold.get_sell_price() { // -> Option u32 = meseta, or None if error + let total_sale = unit_price * amount as u32; + if character.meseta + total_sale <= 999999 { + character.meseta += total_sale; + match item_sold { + InventoryItem::Individual(i) => { + entity_gateway.change_item_location(&i.entity_id, ItemLocation::SoldToShop).await?; + inventory.remove_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?; + }, + InventoryItem::Stacked(s) => { + match amount.cmp(&s.count()) { + Ordering::Less | Ordering::Equal => { + sold_item_handle.consume(amount)?; + }, + // TODO: put a real error here + Ordering::Greater => {println!("i can't believe you've done this.");}, + }; + }, + } + entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?; + entity_gateway.save_character(&character).await?; + } else { + return Err(ItemManagerError::WalletFull.into()); + } + } else { + return Err(ItemManagerError::ItemNotSellable.into()); + } + } else { + return Err(ItemManagerError::ItemIdNotInInventory(item_id).into()) + } + // TODO: why did i put this + Ok(()) + } + // TODO: check if slot exists before putting units into it pub async fn player_equips_item(&mut self, entity_gateway: &mut EG, diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs index b2cb864..7a650a7 100644 --- a/src/ship/packet/handler/direct_message.rs +++ b/src/ship/packet/handler/direct_message.rs @@ -370,11 +370,12 @@ where } }; - if client.character.meseta < item.price() as u32 { + // TODO: stop giving away wares for free + if client.character.meseta < (item.price() * buy_item.amount as usize) as u32 { return Err(ShipError::ShopError.into()) } - client.character.meseta -= item.price() as u32; + client.character.meseta -= (item.price() * buy_item.amount as usize) as u32; entity_gateway.save_character(&client.character).await?; let inventory_item = item_manager.player_buys_item(entity_gateway, &client.character, item, ClientItemId(buy_item.item_id), buy_item.amount as usize).await?; diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs index 39d3717..1ded48e 100644 --- a/src/ship/packet/handler/message.rs +++ b/src/ship/packet/handler/message.rs @@ -110,7 +110,7 @@ pub fn drop_coordinates(id: ClientId, item_id: ClientItemId(drop_coordinates.item_id), }); - Ok(Box::new(None.into_iter())) + Ok(Box::new(None.into_iter())) // TODO: do we need to send a packet here? } pub async fn no_longer_has_item(id: ClientId, @@ -254,7 +254,7 @@ where if client.character.meseta >= charge.meseta { client.character.meseta -= charge.meseta; entity_gateway.save_character(&client.character).await?; - Ok(Box::new(None.into_iter())) + Ok(Box::new(None.into_iter())) // TODO: should probably tell other players we used charge and lost money? } else { Err(ShipError::NotEnoughMeseta(id, client.character.meseta).into()) } @@ -274,7 +274,7 @@ where let item_used_type = item_manager.player_consumes_tool(entity_gateway, &mut client.character, ClientItemId(player_use_tool.item_id), 1).await?; item_manager.use_item(item_used_type, entity_gateway, &mut client.character).await?; - Ok(Box::new(None.into_iter())) + Ok(Box::new(None.into_iter())) // TODO: should probably tell other players we used an item } pub async fn player_used_medical_center(id: ClientId, @@ -333,7 +333,7 @@ where 0 }; item_manager.player_equips_item(entity_gateway, &client.character, ClientItemId(pkt.item_id), equip_slot).await?; - Ok(Box::new(None.into_iter())) + Ok(Box::new(None.into_iter())) // TODO: tell other players you equipped an item } pub async fn player_unequips_item(id: ClientId, @@ -347,7 +347,7 @@ where { let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; item_manager.player_unequips_item(entity_gateway, &client.character, ClientItemId(pkt.item_id)).await?; - Ok(Box::new(None.into_iter())) + Ok(Box::new(None.into_iter())) // TODO: tell other players if you unequip an item } pub async fn player_sorts_items(id: ClientId, @@ -361,5 +361,21 @@ where { let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; item_manager.player_sorts_items(entity_gateway, &client.character, pkt.item_ids).await?; - Ok(Box::new(None.into_iter())) // Do clients care about the order of other clients items? + Ok(Box::new(None.into_iter())) // TODO: clients probably care about each others item orders +} + +pub async fn player_sells_item (id: ClientId, + sold_item: &PlayerSoldItem, + entity_gateway: &mut EG, + // client_location: &ClientLocation, + clients: &mut Clients, + item_manager: &mut ItemManager) + -> Result + Send>, anyhow::Error> +where + EG: EntityGateway +{ + let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; + item_manager.player_sells_item(entity_gateway, &mut client.character, ClientItemId(sold_item.item_id), sold_item.amount as usize).await?; + // TODO: send the packet to other clients + Ok(Box::new(None.into_iter())) } diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 8091647..ae9255d 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -485,6 +485,9 @@ impl ShipServerState { GameMessage::SortItems(sort_items) => { handler::message::player_sorts_items(id, sort_items, &mut self.entity_gateway, &self.clients, &mut self.item_manager).await? }, + GameMessage::PlayerSoldItem(player_sold_item) => { + handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await? + }, _ => { let cmsg = msg.clone(); let block = self.blocks.with_client(id, &self.clients)?; diff --git a/src/ship/shops/armor.rs b/src/ship/shops/armor.rs index 789db56..282cf96 100644 --- a/src/ship/shops/armor.rs +++ b/src/ship/shops/armor.rs @@ -90,6 +90,20 @@ impl ShopItem for ArmorShopItem { } } +impl ArmorShopItem { + pub fn armor_from_item(a: &Armor) -> ArmorShopItem { + ArmorShopItem::Frame(a.armor, a.slots as usize) + } + + pub fn shield_from_item(s: &Shield) -> ArmorShopItem { + ArmorShopItem::Barrier(s.shield) + } + + pub fn unit_from_item(u: &Unit) -> ArmorShopItem { + ArmorShopItem::Unit(u.unit) + } +} + #[derive(Debug, Deserialize, Clone)] struct FrameTierItem { diff --git a/src/ship/shops/tool.rs b/src/ship/shops/tool.rs index d3a8e4b..e68f38d 100644 --- a/src/ship/shops/tool.rs +++ b/src/ship/shops/tool.rs @@ -96,6 +96,16 @@ impl ShopItem for ToolShopItem { } } +impl ToolShopItem { + pub fn tool_from_item(t: &Tool) -> ToolShopItem { + ToolShopItem::Tool(t.tool) + } + + pub fn tech_from_item(d: &TechniqueDisk) -> ToolShopItem { + ToolShopItem::Tech(*d) + } +} + #[derive(Debug, Deserialize)] struct ToolTable(Vec); diff --git a/src/ship/shops/weapon.rs b/src/ship/shops/weapon.rs index 6818f23..cecec0c 100644 --- a/src/ship/shops/weapon.rs +++ b/src/ship/shops/weapon.rs @@ -27,7 +27,7 @@ pub struct WeaponShopItem { weapon: WeaponType, special: Option, grind: usize, - attributes: [Option; 2], + attributes: [Option; 3], } impl PartialEq for WeaponShopItem { @@ -120,7 +120,6 @@ impl ShopItem for WeaponShopItem { }).unwrap_or(0.0); price += special * special * 1000.0; - price as usize }) .unwrap_or(0xFFFF) @@ -143,6 +142,17 @@ impl ShopItem for WeaponShopItem { } } +impl WeaponShopItem { + pub fn weapon_from_item(w: &Weapon) -> WeaponShopItem { + WeaponShopItem { + weapon: w.weapon, + special: w.special, + grind: w.grind as usize, + attributes: w.attrs, + } + } +} + #[derive(Debug, Deserialize)] struct WeaponTableTierEntry { @@ -512,10 +522,10 @@ impl WeaponShop { }; WeaponShopItem { - weapon, - grind, - special, - attributes: [attr1, attr2], + weapon: weapon, + grind: grind, + special: special, + attributes: [attr1, attr2, None], } } -- 2.36.0 From 78f470411377c48ac4b73b26673d3b59a7eeb711 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 00:26:52 +0000 Subject: [PATCH 02/34] fix test. dont let shop give away free items --- tests/test_shops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_shops.rs b/tests/test_shops.rs index ade8ccf..1838414 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -211,7 +211,7 @@ async fn test_player_buys_multiple_from_tool_shop() { let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); - assert!(c1.meseta < 999999); + assert_eq!(c1.meseta, 999749); let p1_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap(); assert_eq!(p1_items.items.len(), 1); p1_items.items[0].with_stacked(|item| { -- 2.36.0 From 78c0ffda040652a4ce9a1cc50311b5044b9ed15a Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 01:08:17 +0000 Subject: [PATCH 03/34] andy vs. clippy round 1 --- src/entity/item/armor.rs | 68 +-------- src/entity/item/mag.rs | 44 +----- src/entity/item/mod.rs | 1 - src/entity/item/shield.rs | 148 +------------------ src/entity/item/tool.rs | 165 +--------------------- src/entity/item/unit.rs | 60 +------- src/entity/item/weapon.rs | 61 +------- src/ship/items/inventory.rs | 22 +-- src/ship/items/manager.rs | 11 +- src/ship/packet/handler/direct_message.rs | 5 +- src/ship/shops/weapon.rs | 6 +- 11 files changed, 28 insertions(+), 563 deletions(-) diff --git a/src/entity/item/armor.rs b/src/entity/item/armor.rs index 4d7291e..25d9c5f 100644 --- a/src/entity/item/armor.rs +++ b/src/entity/item/armor.rs @@ -331,72 +331,6 @@ impl Armor { } pub fn is_rare_item(self) -> bool { - match self.armor { - ArmorType::HunterField => true, - ArmorType::RangerField => true, - ArmorType::ForceField => true, - ArmorType::RevivalGarment => true, - ArmorType::SpiritGarment => true, - ArmorType::StinkFrame => true, - ArmorType::DPartsVer101 => true, - ArmorType::DPartsVer210 => true, - ArmorType::ParasiteWearDeRol => true, - ArmorType::ParasiteWearNelgal => true, - ArmorType::ParasiteWearVajulla => true, - ArmorType::SensePlate => true, - ArmorType::GravitonPlate => true, - ArmorType::AttributePlate => true, - ArmorType::FlowensFrame => true, - ArmorType::CustomFrameVerOo => true, - ArmorType::DbsArmor => true, - ArmorType::GuardWave => true, - ArmorType::DfField => true, - ArmorType::LuminousField => true, - ArmorType::ChuChuFever => true, - ArmorType::LoveHeart => true, - ArmorType::FlameGarment => true, - ArmorType::VirusArmorLafuteria => true, - ArmorType::BrightnessCircle => true, - ArmorType::AuraField => true, - ArmorType::ElectroFrame => true, - ArmorType::SacredCloth => true, - ArmorType::SmokingPlate => true, - ArmorType::StarCuirass => true, - ArmorType::BlackHoundCuirass => true, - ArmorType::MorningPrayer => true, - ArmorType::BlackOdoshiDomaru => true, - ArmorType::RedOdoshiDomaru => true, - ArmorType::BlackOdoshiRedNimaidou => true, - ArmorType::BlueOdoshiVioletNimaidou => true, - ArmorType::DirtyLifejacket => true, - ArmorType::KroesSweater => true, - ArmorType::WeddingDress => true, - ArmorType::SonicteamArmor => true, - ArmorType::RedCoat => true, - ArmorType::Thirteen => true, - ArmorType::MotherGarb => true, - ArmorType::MotherGarbPlus => true, - ArmorType::DressPlate => true, - ArmorType::Sweetheart => true, - ArmorType::IgnitionCloak => true, - ArmorType::CongealCloak => true, - ArmorType::TempestCloak => true, - ArmorType::CursedCloak => true, - ArmorType::SelectCloak => true, - ArmorType::SpiritCuirass => true, - ArmorType::RevivalCuriass => true, - ArmorType::AllianceUniform => true, - ArmorType::OfficerUniform => true, - ArmorType::CommanderUniform => true, - ArmorType::CrimsonCoat => true, - ArmorType::InfantryGear => true, - ArmorType::LieutenantGear => true, - ArmorType::InfantryMantle => true, - ArmorType::LieutenantMantle => true, - ArmorType::UnionField => true, - ArmorType::SamuraiArmor => true, - ArmorType::StealthSuit => true, - _ => false, - } + matches!(self.armor, ArmorType::HunterField | ArmorType::RangerField | ArmorType::ForceField | ArmorType::RevivalGarment | ArmorType::SpiritGarment | ArmorType::StinkFrame | ArmorType::DPartsVer101 | ArmorType::DPartsVer210 | ArmorType::ParasiteWearDeRol | ArmorType::ParasiteWearNelgal | ArmorType::ParasiteWearVajulla | ArmorType::SensePlate | ArmorType::GravitonPlate | ArmorType::AttributePlate | ArmorType::FlowensFrame | ArmorType::CustomFrameVerOo | ArmorType::DbsArmor | ArmorType::GuardWave | ArmorType::DfField | ArmorType::LuminousField | ArmorType::ChuChuFever | ArmorType::LoveHeart | ArmorType::FlameGarment | ArmorType::VirusArmorLafuteria | ArmorType::BrightnessCircle | ArmorType::AuraField | ArmorType::ElectroFrame | ArmorType::SacredCloth | ArmorType::SmokingPlate | ArmorType::StarCuirass | ArmorType::BlackHoundCuirass | ArmorType::MorningPrayer | ArmorType::BlackOdoshiDomaru | ArmorType::RedOdoshiDomaru | ArmorType::BlackOdoshiRedNimaidou | ArmorType::BlueOdoshiVioletNimaidou | ArmorType::DirtyLifejacket | ArmorType::KroesSweater | ArmorType::WeddingDress | ArmorType::SonicteamArmor | ArmorType::RedCoat | ArmorType::Thirteen | ArmorType::MotherGarb | ArmorType::MotherGarbPlus | ArmorType::DressPlate | ArmorType::Sweetheart | ArmorType::IgnitionCloak | ArmorType::CongealCloak | ArmorType::TempestCloak | ArmorType::CursedCloak | ArmorType::SelectCloak | ArmorType::SpiritCuirass | ArmorType::RevivalCuriass | ArmorType::AllianceUniform | ArmorType::OfficerUniform | ArmorType::CommanderUniform | ArmorType::CrimsonCoat | ArmorType::InfantryGear | ArmorType::LieutenantGear | ArmorType::InfantryMantle | ArmorType::LieutenantMantle | ArmorType::UnionField | ArmorType::SamuraiArmor | ArmorType::StealthSuit) } } diff --git a/src/entity/item/mag.rs b/src/entity/item/mag.rs index b5aebd6..e7a6d70 100644 --- a/src/entity/item/mag.rs +++ b/src/entity/item/mag.rs @@ -1101,49 +1101,7 @@ impl Mag { // TODO: is this even needed? mags are not shop sellable...yet pub fn is_rare_item(self) -> bool { - match self.mag { - MagType::Pitri => true, - MagType::Soniti => true, - MagType::Preta => true, - MagType::Churel => true, - MagType::Robochao => true, - MagType::OpaOpa => true, - MagType::Pian => true, - MagType::Chao => true, - MagType::ChuChu => true, - MagType::KapuKapu => true, - MagType::AngelsWing => true, - MagType::DevilsWing => true, - MagType::Elenor => true, - MagType::MarkIII => true, - MagType::MasterSystem => true, - MagType::Genesis => true, - MagType::SegaSaturn => true, - MagType::Dreamcast => true, - MagType::Hamburger => true, - MagType::PanzersTail => true, - MagType::DevilsTail => true, - MagType::Deva => true, - MagType::Rati => true, - MagType::Savitri => true, - MagType::Rukmin => true, - MagType::Pushan => true, - MagType::Diwari => true, - MagType::Sato => true, - MagType::Bhima => true, - MagType::Nidra => true, - MagType::GeungSi => true, - MagType::Tellusis => true, - MagType::StrikerUnit => true, - MagType::Pioneer => true, - MagType::Puyo => true, - MagType::Moro => true, - MagType::Rappy => true, - MagType::Yahoo => true, - MagType::GaelGiel => true, - MagType::Agastya => true, - _ => false, - } + matches!(self.mag, MagType::Pitri | MagType::Soniti | MagType::Preta | MagType::Churel | MagType::Robochao | MagType::OpaOpa | MagType::Pian | MagType::Chao | MagType::ChuChu | MagType::KapuKapu | MagType::AngelsWing | MagType::DevilsWing | MagType::Elenor | MagType::MarkIII | MagType::MasterSystem | MagType::Genesis | MagType::SegaSaturn | MagType::Dreamcast | MagType::Hamburger | MagType::PanzersTail | MagType::DevilsTail | MagType::Deva | MagType::Rati | MagType::Savitri | MagType::Rukmin | MagType::Pushan | MagType::Diwari | MagType::Sato | MagType::Bhima | MagType::Nidra | MagType::GeungSi | MagType::Tellusis | MagType::StrikerUnit | MagType::Pioneer | MagType::Puyo | MagType::Moro | MagType::Rappy | MagType::Yahoo | MagType::GaelGiel | MagType::Agastya) } } diff --git a/src/entity/item/mod.rs b/src/entity/item/mod.rs index 9a0a0c8..8e8c6d4 100644 --- a/src/entity/item/mod.rs +++ b/src/entity/item/mod.rs @@ -12,7 +12,6 @@ use serde::{Serialize, Deserialize}; use crate::entity::character::CharacterEntityId; use crate::ship::map::MapArea; use crate::ship::drops::ItemDropType; -use crate::ship::shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem}; #[derive(PartialEq, Copy, Clone, Debug, Hash, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct ItemEntityId(pub u32); diff --git a/src/entity/item/shield.rs b/src/entity/item/shield.rs index 2f494cd..40faf4e 100644 --- a/src/entity/item/shield.rs +++ b/src/entity/item/shield.rs @@ -550,152 +550,6 @@ impl Shield { } pub fn is_rare_item(self) -> bool { - match self.shield { - ShieldType::InvisibleGuard => true, - ShieldType::SacredGuard => true, - ShieldType::SPartsVer116 => true, - ShieldType::SPartsVer201 => true, - ShieldType::LightRelief => true, - ShieldType::ShieldOfDelsaber => true, - ShieldType::ForceWall => true, - ShieldType::RangerWall => true, - ShieldType::HunterWall => true, - ShieldType::AttributeWall => true, - ShieldType::SecretGear => true, - ShieldType::CombatGear => true, - ShieldType::ProtoRegeneGear => true, - ShieldType::RegenerateGear => true, - ShieldType::RegeneGearAdv => true, - ShieldType::FlowensShield => true, - ShieldType::CustomBarrierVerOo => true, - ShieldType::DbsShield => true, - ShieldType::RedRing => true, - ShieldType::TripolicShield => true, - ShieldType::StandstillShield => true, - ShieldType::SafetyHeart => true, - ShieldType::KasamiBracer => true, - ShieldType::GodsShieldSuzaku => true, - ShieldType::GodsShieldGenbu => true, - ShieldType::GodsShieldByakko => true, - ShieldType::GodsShieldSeiryu => true, - ShieldType::HuntersShell => true, - ShieldType::RicosGlasses => true, - ShieldType::RicosEarring => true, - ShieldType::BlueRing => true, - ShieldType::Barrier2 => true, - ShieldType::SecureFeet => true, - ShieldType::Barrier3 => true, - ShieldType::Barrier4 => true, - ShieldType::Barrier5 => true, - ShieldType::Barrier6 => true, - ShieldType::RestaMerge => true, - ShieldType::AntiMerge => true, - ShieldType::ShiftaMerge => true, - ShieldType::DebandMerge => true, - ShieldType::FoieMerge => true, - ShieldType::GifoieMerge => true, - ShieldType::RafoieMerge => true, - ShieldType::RedMerge => true, - ShieldType::BartaMerge => true, - ShieldType::GibartaMerge => true, - ShieldType::RabartaMerge => true, - ShieldType::BlueMerge => true, - ShieldType::ZondeMerge => true, - ShieldType::GizondeMerge => true, - ShieldType::RazondeMerge => true, - ShieldType::YellowMerge => true, - ShieldType::RecoveryBarrier => true, - ShieldType::AssistBarrier => true, - ShieldType::RedBarrier => true, - ShieldType::BlueBarrier => true, - ShieldType::YellowBarrier => true, - ShieldType::WeaponsGoldShield => true, - ShieldType::BlackGear => true, - ShieldType::WorksGuard => true, - ShieldType::RagolRing => true, - ShieldType::BlueRing2 => true, - ShieldType::BlueRing3 => true, - ShieldType::BlueRing4 => true, - ShieldType::BlueRing5 => true, - ShieldType::BlueRing6 => true, - ShieldType::BlueRing7 => true, - ShieldType::BlueRing8 => true, - ShieldType::BlueRing9 => true, - ShieldType::GreenRing => true, - ShieldType::GreenRing2 => true, - ShieldType::GreenRing3 => true, - ShieldType::GreenRing4 => true, - ShieldType::GreenRing5 => true, - ShieldType::GreenRing6 => true, - ShieldType::GreenRing7 => true, - ShieldType::GreenRing8 => true, - ShieldType::YellowRing => true, - ShieldType::YellowRing2 => true, - ShieldType::YellowRing3 => true, - ShieldType::YellowRing4 => true, - ShieldType::YellowRing5 => true, - ShieldType::YellowRing6 => true, - ShieldType::YellowRing7 => true, - ShieldType::YellowRing8 => true, - ShieldType::PurpleRing => true, - ShieldType::PurpleRing2 => true, - ShieldType::PurpleRing3 => true, - ShieldType::PurpleRing4 => true, - ShieldType::PurpleRing5 => true, - ShieldType::PurpleRing6 => true, - ShieldType::PurpleRing7 => true, - ShieldType::PurpleRing8 => true, - ShieldType::WhiteRing => true, - ShieldType::WhiteRing2 => true, - ShieldType::WhiteRing3 => true, - ShieldType::WhiteRing4 => true, - ShieldType::WhiteRing5 => true, - ShieldType::WhiteRing6 => true, - ShieldType::WhiteRing7 => true, - ShieldType::WhiteRing8 => true, - ShieldType::BlackRing => true, - ShieldType::BlackRing2 => true, - ShieldType::BlackRing3 => true, - ShieldType::BlackRing4 => true, - ShieldType::BlackRing5 => true, - ShieldType::BlackRing6 => true, - ShieldType::BlackRing7 => true, - ShieldType::BlackRing8 => true, - ShieldType::WeaponsSilverShield => true, - ShieldType::WeaponsCopperShield => true, - ShieldType::Gratia => true, - ShieldType::TripolicReflector => true, - ShieldType::StrikerPlus => true, - ShieldType::RegenerateGearBP => true, - ShieldType::Rupika => true, - ShieldType::YataMirror => true, - ShieldType::BunnyEars => true, - ShieldType::CatEars => true, - ShieldType::ThreeSeals => true, - ShieldType::GodsShieldKouryu => true, - ShieldType::DfShield => true, - ShieldType::FromTheDepths => true, - ShieldType::DeRolLeShield => true, - ShieldType::HoneycombReflector => true, - ShieldType::Epsiguard => true, - ShieldType::AngelRing => true, - ShieldType::UnionGuard => true, - ShieldType::UnionGuard2 => true, - ShieldType::UnionGuard3 => true, - ShieldType::UnionGuard4 => true, - ShieldType::StinkShield => true, - ShieldType::Unknownb => true, - ShieldType::Genpei => true, - ShieldType::Genpei2 => true, - ShieldType::Genpei3 => true, - ShieldType::Genpei4 => true, - ShieldType::Genpei5 => true, - ShieldType::Genpei6 => true, - ShieldType::Genpei7 => true, - ShieldType::Genpei8 => true, - ShieldType::Genpei9 => true, - ShieldType::Genpei10 => true, - _ => false, - } + matches!(self.shield, ShieldType::InvisibleGuard | ShieldType::SacredGuard | ShieldType::SPartsVer116 | ShieldType::SPartsVer201 | ShieldType::LightRelief | ShieldType::ShieldOfDelsaber | ShieldType::ForceWall | ShieldType::RangerWall | ShieldType::HunterWall | ShieldType::AttributeWall | ShieldType::SecretGear | ShieldType::CombatGear | ShieldType::ProtoRegeneGear | ShieldType::RegenerateGear | ShieldType::RegeneGearAdv | ShieldType::FlowensShield | ShieldType::CustomBarrierVerOo | ShieldType::DbsShield | ShieldType::RedRing | ShieldType::TripolicShield | ShieldType::StandstillShield | ShieldType::SafetyHeart | ShieldType::KasamiBracer | ShieldType::GodsShieldSuzaku | ShieldType::GodsShieldGenbu | ShieldType::GodsShieldByakko | ShieldType::GodsShieldSeiryu | ShieldType::HuntersShell | ShieldType::RicosGlasses | ShieldType::RicosEarring | ShieldType::BlueRing | ShieldType::Barrier2 | ShieldType::SecureFeet | ShieldType::Barrier3 | ShieldType::Barrier4 | ShieldType::Barrier5 | ShieldType::Barrier6 | ShieldType::RestaMerge | ShieldType::AntiMerge | ShieldType::ShiftaMerge | ShieldType::DebandMerge | ShieldType::FoieMerge | ShieldType::GifoieMerge | ShieldType::RafoieMerge | ShieldType::RedMerge | ShieldType::BartaMerge | ShieldType::GibartaMerge | ShieldType::RabartaMerge | ShieldType::BlueMerge | ShieldType::ZondeMerge | ShieldType::GizondeMerge | ShieldType::RazondeMerge | ShieldType::YellowMerge | ShieldType::RecoveryBarrier | ShieldType::AssistBarrier | ShieldType::RedBarrier | ShieldType::BlueBarrier | ShieldType::YellowBarrier | ShieldType::WeaponsGoldShield | ShieldType::BlackGear | ShieldType::WorksGuard | ShieldType::RagolRing | ShieldType::BlueRing2 | ShieldType::BlueRing3 | ShieldType::BlueRing4 | ShieldType::BlueRing5 | ShieldType::BlueRing6 | ShieldType::BlueRing7 | ShieldType::BlueRing8 | ShieldType::BlueRing9 | ShieldType::GreenRing | ShieldType::GreenRing2 | ShieldType::GreenRing3 | ShieldType::GreenRing4 | ShieldType::GreenRing5 | ShieldType::GreenRing6 | ShieldType::GreenRing7 | ShieldType::GreenRing8 | ShieldType::YellowRing | ShieldType::YellowRing2 | ShieldType::YellowRing3 | ShieldType::YellowRing4 | ShieldType::YellowRing5 | ShieldType::YellowRing6 | ShieldType::YellowRing7 | ShieldType::YellowRing8 | ShieldType::PurpleRing | ShieldType::PurpleRing2 | ShieldType::PurpleRing3 | ShieldType::PurpleRing4 | ShieldType::PurpleRing5 | ShieldType::PurpleRing6 | ShieldType::PurpleRing7 | ShieldType::PurpleRing8 | ShieldType::WhiteRing | ShieldType::WhiteRing2 | ShieldType::WhiteRing3 | ShieldType::WhiteRing4 | ShieldType::WhiteRing5 | ShieldType::WhiteRing6 | ShieldType::WhiteRing7 | ShieldType::WhiteRing8 | ShieldType::BlackRing | ShieldType::BlackRing2 | ShieldType::BlackRing3 | ShieldType::BlackRing4 | ShieldType::BlackRing5 | ShieldType::BlackRing6 | ShieldType::BlackRing7 | ShieldType::BlackRing8 | ShieldType::WeaponsSilverShield | ShieldType::WeaponsCopperShield | ShieldType::Gratia | ShieldType::TripolicReflector | ShieldType::StrikerPlus | ShieldType::RegenerateGearBP | ShieldType::Rupika | ShieldType::YataMirror | ShieldType::BunnyEars | ShieldType::CatEars | ShieldType::ThreeSeals | ShieldType::GodsShieldKouryu | ShieldType::DfShield | ShieldType::FromTheDepths | ShieldType::DeRolLeShield | ShieldType::HoneycombReflector | ShieldType::Epsiguard | ShieldType::AngelRing | ShieldType::UnionGuard | ShieldType::UnionGuard2 | ShieldType::UnionGuard3 | ShieldType::UnionGuard4 | ShieldType::StinkShield | ShieldType::Unknownb | ShieldType::Genpei | ShieldType::Genpei2 | ShieldType::Genpei3 | ShieldType::Genpei4 | ShieldType::Genpei5 | ShieldType::Genpei6 | ShieldType::Genpei7 | ShieldType::Genpei8 | ShieldType::Genpei9 | ShieldType::Genpei10) } } diff --git a/src/entity/item/tool.rs b/src/entity/item/tool.rs index b20845f..0fd2167 100644 --- a/src/entity/item/tool.rs +++ b/src/entity/item/tool.rs @@ -682,172 +682,11 @@ impl Tool { } pub fn is_rare_item(self) -> bool { - match self.tool { - ToolType::CellOfMag502 => true, - ToolType::CellOfMag213 => true, - ToolType::PartsOfRobochao => true, - ToolType::HeartOfOpaOpa => true, - ToolType::HeartOfPian => true, - ToolType::HeartOfChao => true, - ToolType::SorcerersRightArm => true, - ToolType::SBeatsArms => true, - ToolType::PArmsArms => true, - ToolType::DelsabersRightArm => true, - ToolType::BringersRightArm => true, - ToolType::DelsabersLeftArm => true, - ToolType::SRedsArms => true, - ToolType::DragonsClaw => true, - ToolType::HildebearsHead => true, - ToolType::HildebluesHead => true, - ToolType::PartsOfBaranz => true, - ToolType::BelrasRightArm => true, - ToolType::GiGuesBody => true, - ToolType::SinowBerillsArms => true, - ToolType::GrassAssassinsArms => true, - ToolType::BoomasRightArm => true, - ToolType::GoboomasRightArm => true, - ToolType::GigoboomasRightArm => true, - ToolType::GalGryphonsWing => true, - ToolType::RappysWing => true, - ToolType::CladdingOfEpsilon => true, - ToolType::DeRolLeShell => true, - ToolType::BerillPhoton => true, - ToolType::ParasiticGeneFlow => true, - ToolType::MagicStoneIritista => true, - ToolType::BlueBlackStone => true, - ToolType::Syncesta => true, - ToolType::MagicWater => true, - ToolType::ParasiticCellTypeD => true, - ToolType::MagicRockHeartKey => true, - ToolType::MagicRockMoola => true, - ToolType::StarAmplifier => true, - ToolType::BookOfHitogata => true, - ToolType::HeartOfChuChu => true, - ToolType::PartsOfEggBlaster => true, - ToolType::HeartOfAngel => true, - ToolType::HeartOfDevil => true, - ToolType::KitOfHamburger => true, - ToolType::PanthersSpirit => true, - ToolType::KitOfMark3 => true, - ToolType::KitOfMasterSystem => true, - ToolType::KitOfGenesis => true, - ToolType::KitOfSegaSaturn => true, - ToolType::KitOfDreamcast => true, - ToolType::AmplifierOfResta => true, - ToolType::AmplifierOfAnti => true, - ToolType::AmplifierOfShifta => true, - ToolType::AmplifierOfDeband => true, - ToolType::AmplifierOfFoie => true, - ToolType::AmplifierOfGifoie => true, - ToolType::AmplifierOfRafoie => true, - ToolType::AmplifierOfBarta => true, - ToolType::AmplifierOfGibarta => true, - ToolType::AmplifierOfRabarta => true, - ToolType::AmplifierOfZonde => true, - ToolType::AmplifierOfGizonde => true, - ToolType::AmplifierOfRazonde => true, - ToolType::AmplifierOfRed => true, - ToolType::AmplifierOfBlue => true, - ToolType::AmplifierOfYellow => true, - ToolType::HeartOfKapuKapu => true, - ToolType::PhotonBooster => true, - ToolType::Addslot => true, - ToolType::PhotonDrop => true, - ToolType::PhotonSphere => true, - ToolType::PhotonCrystal => true, - ToolType::SecretTicket => true, - ToolType::PhotonTicket => true, - ToolType::BookOfKatana1 => true, - ToolType::BookOfKatana2 => true, - ToolType::BookOfKatana3 => true, - ToolType::WeaponsBronzeBadge => true, - ToolType::WeaponsSilverBadge => true, - ToolType::WeaponsGoldBadge => true, - ToolType::WeaponsCrystalBadge => true, - ToolType::WeaponsSteelBadge => true, - ToolType::WeaponsAluminumBadge => true, - ToolType::WeaponsLeatherBadge => true, - ToolType::WeaponsBoneBadge => true, - ToolType::LetterOfAppreciation => true, - ToolType::ItemTicket => true, - ToolType::ValentinesChocolate => true, - ToolType::NewYearsCard => true, - ToolType::ChristmasCard => true, - ToolType::BirthdayCard => true, - ToolType::ProofOfSonicTeam => true, - ToolType::SpecialEventTicket => true, - ToolType::FlowerBouquet => true, - ToolType::Cake => true, - ToolType::Accessories => true, - ToolType::MrNakasBusinessCard => true, - ToolType::Present => true, - ToolType::Chocolate => true, - ToolType::Candy => true, - ToolType::Cake2 => true, - ToolType::WeaponsSilverBadge2 => true, - ToolType::WeaponsGoldBadge2 => true, - ToolType::WeaponsCrystalBadge2 => true, - ToolType::WeaponsSteelBadge2 => true, - ToolType::WeaponsAluminumBadge2 => true, - ToolType::WeaponsLeatherBadge2 => true, - ToolType::WeaponsBoneBadge2 => true, - ToolType::Bouquet => true, - ToolType::Decoction => true, - ToolType::ChristmasPresent => true, - ToolType::EasterEgg => true, - ToolType::JackOLantern => true, - ToolType::DiskVol1WeddingMarch => true, - ToolType::DiskVol2DayLight => true, - ToolType::DiskVol3BurningRangers => true, - ToolType::DiskVol4OpenYourHeart => true, - ToolType::DiskVol5LiveLearn => true, - ToolType::DiskVol6Nights => true, - ToolType::DiskVol7EndingThemePianoVer => true, - ToolType::DiskVol8HeartToHeart => true, - ToolType::DiskVol9StrangeBlue => true, - ToolType::DiskVol10ReunionSystem => true, - ToolType::DiskVol11Pinnacles => true, - ToolType::DiskVol12FightInsideTheSpaceship => true, - ToolType::HuntersReport => true, - ToolType::HuntersReport2 => true, - ToolType::HuntersReport3 => true, - ToolType::HuntersReport4 => true, - ToolType::HuntersReport5 => true, - ToolType::Tablet => true, - ToolType::Unknown2 => true, - ToolType::DragonScale => true, - ToolType::HeavenStrikerCoat => true, - ToolType::PioneerParts => true, - ToolType::AmitiesMemo => true, - ToolType::HeartOfMorolian => true, - ToolType::RappysBeak => true, - ToolType::YahoosEngine => true, - ToolType::DPhotonCore => true, - ToolType::LibertaKit => true, - ToolType::CellOfMag0503 => true, - ToolType::CellOfMag0504 => true, - ToolType::CellOfMag0505 => true, - ToolType::CellOfMag0506 => true, - ToolType::CellOfMag0507 => true, - ToolType::TeamPoints500 => true, - ToolType::TeamPoints1000 => true, - ToolType::TeamPoints5000 => true, - ToolType::TeamPoints10000 => true, - _ => false, - } + matches!(self.tool, ToolType::CellOfMag502 | ToolType::CellOfMag213 | ToolType::PartsOfRobochao | ToolType::HeartOfOpaOpa | ToolType::HeartOfPian | ToolType::HeartOfChao | ToolType::SorcerersRightArm | ToolType::SBeatsArms | ToolType::PArmsArms | ToolType::DelsabersRightArm | ToolType::BringersRightArm | ToolType::DelsabersLeftArm | ToolType::SRedsArms | ToolType::DragonsClaw | ToolType::HildebearsHead | ToolType::HildebluesHead | ToolType::PartsOfBaranz | ToolType::BelrasRightArm | ToolType::GiGuesBody | ToolType::SinowBerillsArms | ToolType::GrassAssassinsArms | ToolType::BoomasRightArm | ToolType::GoboomasRightArm | ToolType::GigoboomasRightArm | ToolType::GalGryphonsWing | ToolType::RappysWing | ToolType::CladdingOfEpsilon | ToolType::DeRolLeShell | ToolType::BerillPhoton | ToolType::ParasiticGeneFlow | ToolType::MagicStoneIritista | ToolType::BlueBlackStone | ToolType::Syncesta | ToolType::MagicWater | ToolType::ParasiticCellTypeD | ToolType::MagicRockHeartKey | ToolType::MagicRockMoola | ToolType::StarAmplifier | ToolType::BookOfHitogata | ToolType::HeartOfChuChu | ToolType::PartsOfEggBlaster | ToolType::HeartOfAngel | ToolType::HeartOfDevil | ToolType::KitOfHamburger | ToolType::PanthersSpirit | ToolType::KitOfMark3 | ToolType::KitOfMasterSystem | ToolType::KitOfGenesis | ToolType::KitOfSegaSaturn | ToolType::KitOfDreamcast | ToolType::AmplifierOfResta | ToolType::AmplifierOfAnti | ToolType::AmplifierOfShifta | ToolType::AmplifierOfDeband | ToolType::AmplifierOfFoie | ToolType::AmplifierOfGifoie | ToolType::AmplifierOfRafoie | ToolType::AmplifierOfBarta | ToolType::AmplifierOfGibarta | ToolType::AmplifierOfRabarta | ToolType::AmplifierOfZonde | ToolType::AmplifierOfGizonde | ToolType::AmplifierOfRazonde | ToolType::AmplifierOfRed | ToolType::AmplifierOfBlue | ToolType::AmplifierOfYellow | ToolType::HeartOfKapuKapu | ToolType::PhotonBooster | ToolType::Addslot | ToolType::PhotonDrop | ToolType::PhotonSphere | ToolType::PhotonCrystal | ToolType::SecretTicket | ToolType::PhotonTicket | ToolType::BookOfKatana1 | ToolType::BookOfKatana2 | ToolType::BookOfKatana3 | ToolType::WeaponsBronzeBadge | ToolType::WeaponsSilverBadge | ToolType::WeaponsGoldBadge | ToolType::WeaponsCrystalBadge | ToolType::WeaponsSteelBadge | ToolType::WeaponsAluminumBadge | ToolType::WeaponsLeatherBadge | ToolType::WeaponsBoneBadge | ToolType::LetterOfAppreciation | ToolType::ItemTicket | ToolType::ValentinesChocolate | ToolType::NewYearsCard | ToolType::ChristmasCard | ToolType::BirthdayCard | ToolType::ProofOfSonicTeam | ToolType::SpecialEventTicket | ToolType::FlowerBouquet | ToolType::Cake | ToolType::Accessories | ToolType::MrNakasBusinessCard | ToolType::Present | ToolType::Chocolate | ToolType::Candy | ToolType::Cake2 | ToolType::WeaponsSilverBadge2 | ToolType::WeaponsGoldBadge2 | ToolType::WeaponsCrystalBadge2 | ToolType::WeaponsSteelBadge2 | ToolType::WeaponsAluminumBadge2 | ToolType::WeaponsLeatherBadge2 | ToolType::WeaponsBoneBadge2 | ToolType::Bouquet | ToolType::Decoction | ToolType::ChristmasPresent | ToolType::EasterEgg | ToolType::JackOLantern | ToolType::DiskVol1WeddingMarch | ToolType::DiskVol2DayLight | ToolType::DiskVol3BurningRangers | ToolType::DiskVol4OpenYourHeart | ToolType::DiskVol5LiveLearn | ToolType::DiskVol6Nights | ToolType::DiskVol7EndingThemePianoVer | ToolType::DiskVol8HeartToHeart | ToolType::DiskVol9StrangeBlue | ToolType::DiskVol10ReunionSystem | ToolType::DiskVol11Pinnacles | ToolType::DiskVol12FightInsideTheSpaceship | ToolType::HuntersReport | ToolType::HuntersReport2 | ToolType::HuntersReport3 | ToolType::HuntersReport4 | ToolType::HuntersReport5 | ToolType::Tablet | ToolType::Unknown2 | ToolType::DragonScale | ToolType::HeavenStrikerCoat | ToolType::PioneerParts | ToolType::AmitiesMemo | ToolType::HeartOfMorolian | ToolType::RappysBeak | ToolType::YahoosEngine | ToolType::DPhotonCore | ToolType::LibertaKit | ToolType::CellOfMag0503 | ToolType::CellOfMag0504 | ToolType::CellOfMag0505 | ToolType::CellOfMag0506 | ToolType::CellOfMag0507 | ToolType::TeamPoints500 | ToolType::TeamPoints1000 | ToolType::TeamPoints5000 | ToolType::TeamPoints10000) } // TODO: do we actually need this function? pub fn is_material(self) -> bool { - match self.tool { - ToolType::PowerMaterial => true, - ToolType::MindMaterial => true, - ToolType::EvadeMaterial => true, - ToolType::HpMaterial => true, - ToolType::TpMaterial => true, - ToolType::DefMaterial => true, - ToolType::LuckMaterial => true, - _ => false, - } + matches!(self.tool, ToolType::PowerMaterial | ToolType::MindMaterial | ToolType::EvadeMaterial | ToolType::HpMaterial | ToolType::TpMaterial | ToolType::DefMaterial | ToolType::LuckMaterial) } } diff --git a/src/entity/item/unit.rs b/src/entity/item/unit.rs index 6e90bb0..31becb0 100644 --- a/src/entity/item/unit.rs +++ b/src/entity/item/unit.rs @@ -386,64 +386,6 @@ impl Unit { } pub fn is_rare_item(self) -> bool { - match self.unit { - UnitType::GodPower => true, - UnitType::GodMind => true, - UnitType::GodArm => true, - UnitType::GodLegs => true, - UnitType::GodHp => true, - UnitType::GodTp => true, - UnitType::GodBody => true, - UnitType::GodLuck => true, - UnitType::HeroAbility => true, - UnitType::GodAbility => true, - UnitType::AllResist => true, - UnitType::SuperResist => true, - UnitType::PerfectResist => true, - UnitType::HpRevival => true, - UnitType::TpRevival => true, - UnitType::PbAmplifier => true, - UnitType::PbGenerate => true, - UnitType::PbCreate => true, - UnitType::DevilTechnique => true, - UnitType::GodTechnique => true, - UnitType::DevilBattle => true, - UnitType::GodBattle => true, - UnitType::CurePoison => true, - UnitType::CureParalysis => true, - UnitType::CureSlow => true, - UnitType::CureConfuse => true, - UnitType::CureFreeze => true, - UnitType::CureShock => true, - UnitType::YasakaniMagatama => true, - UnitType::V101 => true, - UnitType::V501 => true, - UnitType::V502 => true, - UnitType::V801 => true, - UnitType::Limiter => true, - UnitType::Adept => true, - UnitType::SwordsmanLore => true, - UnitType::ProofOfSwordSaint => true, - UnitType::Smartlink => true, - UnitType::DivineProtection => true, - UnitType::HeavenlyBattle => true, - UnitType::HeavenlyPower => true, - UnitType::HeavenlyMind => true, - UnitType::HeavenlyArms => true, - UnitType::HeavenlyLegs => true, - UnitType::HeavenlyBody => true, - UnitType::HeavenlyLuck => true, - UnitType::HeavenlyAbility => true, - UnitType::CenturionAbility => true, - UnitType::FriendRing => true, - UnitType::HeavenlyHp => true, - UnitType::HeavenlyTp => true, - UnitType::HeavenlyResist => true, - UnitType::HeavenlyTechnique => true, - UnitType::HpRessurection => true, - UnitType::TpRessurection => true, - UnitType::PbIncrease => true, - _ => false, - } + matches!(self.unit, UnitType::GodPower | UnitType::GodMind | UnitType::GodArm | UnitType::GodLegs | UnitType::GodHp | UnitType::GodTp | UnitType::GodBody | UnitType::GodLuck | UnitType::HeroAbility | UnitType::GodAbility | UnitType::AllResist | UnitType::SuperResist | UnitType::PerfectResist | UnitType::HpRevival | UnitType::TpRevival | UnitType::PbAmplifier | UnitType::PbGenerate | UnitType::PbCreate | UnitType::DevilTechnique | UnitType::GodTechnique | UnitType::DevilBattle | UnitType::GodBattle | UnitType::CurePoison | UnitType::CureParalysis | UnitType::CureSlow | UnitType::CureConfuse | UnitType::CureFreeze | UnitType::CureShock | UnitType::YasakaniMagatama | UnitType::V101 | UnitType::V501 | UnitType::V502 | UnitType::V801 | UnitType::Limiter | UnitType::Adept | UnitType::SwordsmanLore | UnitType::ProofOfSwordSaint | UnitType::Smartlink | UnitType::DivineProtection | UnitType::HeavenlyBattle | UnitType::HeavenlyPower | UnitType::HeavenlyMind | UnitType::HeavenlyArms | UnitType::HeavenlyLegs | UnitType::HeavenlyBody | UnitType::HeavenlyLuck | UnitType::HeavenlyAbility | UnitType::CenturionAbility | UnitType::FriendRing | UnitType::HeavenlyHp | UnitType::HeavenlyTp | UnitType::HeavenlyResist | UnitType::HeavenlyTechnique | UnitType::HpRessurection | UnitType::TpRessurection | UnitType::PbIncrease) } } diff --git a/src/entity/item/weapon.rs b/src/entity/item/weapon.rs index 5d20e71..d07e34d 100644 --- a/src/entity/item/weapon.rs +++ b/src/entity/item/weapon.rs @@ -1587,66 +1587,7 @@ impl Weapon { // TODO: invert this? ie: handgun, saber, dagger etc. => false, _ => true? pub fn is_rare_item(self) -> bool { - match self.weapon { - WeaponType::Saber => false, - WeaponType::Brand => false, - WeaponType::Buster => false, - WeaponType::Pallasch => false, - WeaponType::Gladius => false, - WeaponType::Sword => false, - WeaponType::Gigush => false, - WeaponType::Breaker => false, - WeaponType::Claymore => false, - WeaponType::Calibur => false, - WeaponType::Dagger => false, - WeaponType::Knife => false, - WeaponType::Blade => false, - WeaponType::Edge => false, - WeaponType::Ripper => false, - WeaponType::Partisan => false, - WeaponType::Halbert => false, - WeaponType::Glaive => false, - WeaponType::Berdys => false, - WeaponType::Gungnir => false, - WeaponType::Slicer => false, - WeaponType::Spinner => false, - WeaponType::Cutter => false, - WeaponType::Sawcer => false, - WeaponType::Diska => false, - WeaponType::Handgun => false, - WeaponType::Autogun => false, - WeaponType::Lockgun => false, - WeaponType::Railgun => false, - WeaponType::Raygun => false, - WeaponType::Rifle => false, - WeaponType::Sniper => false, - WeaponType::Blaster => false, - WeaponType::Beam => false, - WeaponType::Laser => false, - WeaponType::Mechgun => false, - WeaponType::Assault => false, - WeaponType::Repeater => false, - WeaponType::Gatling => false, - WeaponType::Vulcan => false, - WeaponType::Shot => false, - WeaponType::Spread => false, - WeaponType::Cannon => false, - WeaponType::Launcher => false, - WeaponType::Arms => false, - WeaponType::Cane => false, - WeaponType::Stick => false, - WeaponType::Mace => false, - WeaponType::Club => false, - WeaponType::Rod => false, - WeaponType::Pole => false, - WeaponType::Pillar => false, - WeaponType::Striker => false, - WeaponType::Wand => false, - WeaponType::Staff => false, - WeaponType::Baton => false, - WeaponType::Scepter => false, - _ => true, - } + !matches!(self.weapon, WeaponType::Saber | WeaponType::Brand | WeaponType::Buster | WeaponType::Pallasch | WeaponType::Gladius | WeaponType::Sword | WeaponType::Gigush | WeaponType::Breaker | WeaponType::Claymore | WeaponType::Calibur | WeaponType::Dagger | WeaponType::Knife | WeaponType::Blade | WeaponType::Edge | WeaponType::Ripper | WeaponType::Partisan | WeaponType::Halbert | WeaponType::Glaive | WeaponType::Berdys | WeaponType::Gungnir | WeaponType::Slicer | WeaponType::Spinner | WeaponType::Cutter | WeaponType::Sawcer | WeaponType::Diska | WeaponType::Handgun | WeaponType::Autogun | WeaponType::Lockgun | WeaponType::Railgun | WeaponType::Raygun | WeaponType::Rifle | WeaponType::Sniper | WeaponType::Blaster | WeaponType::Beam | WeaponType::Laser | WeaponType::Mechgun | WeaponType::Assault | WeaponType::Repeater | WeaponType::Gatling | WeaponType::Vulcan | WeaponType::Shot | WeaponType::Spread | WeaponType::Cannon | WeaponType::Launcher | WeaponType::Arms | WeaponType::Cane | WeaponType::Stick | WeaponType::Mace | WeaponType::Club | WeaponType::Rod | WeaponType::Pole | WeaponType::Pillar | WeaponType::Striker | WeaponType::Wand | WeaponType::Staff | WeaponType::Baton | WeaponType::Scepter) } } diff --git a/src/ship/items/inventory.rs b/src/ship/items/inventory.rs index 81bd733..7de42e9 100644 --- a/src/ship/items/inventory.rs +++ b/src/ship/items/inventory.rs @@ -1,9 +1,9 @@ use std::cmp::Ordering; use thiserror::Error; -use libpso::character::character;//::InventoryItem; +use libpso::character::character; use crate::entity::character::CharacterEntityId; use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, ItemType, ItemLocation, InventoryEntity, InventoryItemEntity, EquippedEntity}; -use crate::entity::item::tool::{Tool, ToolType}; +use crate::entity::item::tool::Tool; use crate::entity::item::mag::Mag; use crate::entity::item::weapon::Weapon; use crate::ship::items::{ClientItemId, BankItem, BankItemHandle}; @@ -235,46 +235,46 @@ impl InventoryItem { return Some(10u32) } // other item factors? - return Some((WeaponShopItem::weapon_from_item(w).price() / 8) as u32) + Some((WeaponShopItem::weapon_from_item(w).price() / 8) as u32) }, ItemDetail::Armor(a) => { if a.is_rare_item() { return Some(10u32) } - return Some((ArmorShopItem::armor_from_item(a).price() / 8) as u32) + Some((ArmorShopItem::armor_from_item(a).price() / 8) as u32) }, ItemDetail::Shield(s) => { if s.is_rare_item() { return Some(10u32) } - return Some((ArmorShopItem::shield_from_item(s).price() / 8) as u32) + Some((ArmorShopItem::shield_from_item(s).price() / 8) as u32) }, ItemDetail::Unit(u) => { if u.is_rare_item() { return Some(10u32) } - return Some((ArmorShopItem::unit_from_item(u).price() / 8) as u32) + Some((ArmorShopItem::unit_from_item(u).price() / 8) as u32) }, ItemDetail::Tool(t) => { if t.is_rare_item() { // TODO: photon drop/sphere etc return Some(10u32) } - return Some((ToolShopItem::tool_from_item(t).price() / 8) as u32) + Some((ToolShopItem::tool_from_item(t).price() / 8) as u32) }, ItemDetail::TechniqueDisk(d) => { // TODO: are all techs the same? - return Some((ToolShopItem::tech_from_item(d).price() / 8) as u32) + Some((ToolShopItem::tech_from_item(d).price() / 8) as u32) }, ItemDetail::Mag(_m) => { //TODO: error. mags are not sellable - return None + None }, ItemDetail::ESWeapon(_e) => { - return Some(10u32) // TODO: check price + Some(10u32) // TODO: check price }, } }, // the number of stacked items sold is handled by the caller. this is just the price of 1 InventoryItem::Stacked(stacked_item) => { - return Some((ToolShopItem::tool_from_item(&stacked_item.tool).price() / 8) as u32) + Some((ToolShopItem::tool_from_item(&stacked_item.tool).price() / 8) as u32) }, } } diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index 65cede0..1186dee 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -1,5 +1,5 @@ use crate::ship::items::ClientItemId; -use std::collections::{HashMap, BTreeMap}; +use std::collections::HashMap; use std::cmp::Ordering; use thiserror::Error; use crate::entity::gateway::EntityGateway; @@ -876,7 +876,7 @@ impl ItemManager { }, } entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?; - entity_gateway.save_character(&character).await?; + entity_gateway.save_character(character).await?; } else { return Err(ItemManagerError::WalletFull.into()); } @@ -947,10 +947,9 @@ impl ItemManager { .ok_or(ItemManagerError::WrongItemType(item_id))?; let entity_id = individual.entity_id; - let mut weapon = individual + let mut weapon = *individual .weapon() - .ok_or(ItemManagerError::WrongItemType(item_id))? - .clone(); + .ok_or(ItemManagerError::WrongItemType(item_id))?; weapon.apply_modifier(&tek); entity_gateway.add_weapon_modifier(&entity_id, tek).await?; @@ -958,7 +957,7 @@ impl ItemManager { inventory.add_item(InventoryItem::Individual(IndividualInventoryItem { entity_id, item_id, - item: ItemDetail::Weapon(weapon.clone()), + item: ItemDetail::Weapon(weapon), }))?; entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?; diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs index 7a650a7..f17f1a1 100644 --- a/src/ship/packet/handler/direct_message.rs +++ b/src/ship/packet/handler/direct_message.rs @@ -436,11 +436,10 @@ where let inventory = item_manager.get_character_inventory(&client.character)?; let item = inventory.get_item_by_id(ClientItemId(tek_request.item_id)) .ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))?; - let mut weapon = item.individual() + let mut weapon = *item.individual() .ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))? .weapon() - .ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))? - .clone(); + .ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))?; weapon.apply_modifier(&item::weapon::WeaponModifier::Tekked { special: special_mod, diff --git a/src/ship/shops/weapon.rs b/src/ship/shops/weapon.rs index cecec0c..7bdae25 100644 --- a/src/ship/shops/weapon.rs +++ b/src/ship/shops/weapon.rs @@ -522,9 +522,9 @@ impl WeaponShop { }; WeaponShopItem { - weapon: weapon, - grind: grind, - special: special, + weapon, + grind, + special, attributes: [attr1, attr2, None], } } -- 2.36.0 From 540c6aae7cd4e33dd95818d7fb30c437e74d12a7 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 02:21:20 +0000 Subject: [PATCH 04/34] rustfmt armor.rs --- src/entity/item/armor.rs | 68 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/src/entity/item/armor.rs b/src/entity/item/armor.rs index 25d9c5f..451852b 100644 --- a/src/entity/item/armor.rs +++ b/src/entity/item/armor.rs @@ -331,6 +331,72 @@ impl Armor { } pub fn is_rare_item(self) -> bool { - matches!(self.armor, ArmorType::HunterField | ArmorType::RangerField | ArmorType::ForceField | ArmorType::RevivalGarment | ArmorType::SpiritGarment | ArmorType::StinkFrame | ArmorType::DPartsVer101 | ArmorType::DPartsVer210 | ArmorType::ParasiteWearDeRol | ArmorType::ParasiteWearNelgal | ArmorType::ParasiteWearVajulla | ArmorType::SensePlate | ArmorType::GravitonPlate | ArmorType::AttributePlate | ArmorType::FlowensFrame | ArmorType::CustomFrameVerOo | ArmorType::DbsArmor | ArmorType::GuardWave | ArmorType::DfField | ArmorType::LuminousField | ArmorType::ChuChuFever | ArmorType::LoveHeart | ArmorType::FlameGarment | ArmorType::VirusArmorLafuteria | ArmorType::BrightnessCircle | ArmorType::AuraField | ArmorType::ElectroFrame | ArmorType::SacredCloth | ArmorType::SmokingPlate | ArmorType::StarCuirass | ArmorType::BlackHoundCuirass | ArmorType::MorningPrayer | ArmorType::BlackOdoshiDomaru | ArmorType::RedOdoshiDomaru | ArmorType::BlackOdoshiRedNimaidou | ArmorType::BlueOdoshiVioletNimaidou | ArmorType::DirtyLifejacket | ArmorType::KroesSweater | ArmorType::WeddingDress | ArmorType::SonicteamArmor | ArmorType::RedCoat | ArmorType::Thirteen | ArmorType::MotherGarb | ArmorType::MotherGarbPlus | ArmorType::DressPlate | ArmorType::Sweetheart | ArmorType::IgnitionCloak | ArmorType::CongealCloak | ArmorType::TempestCloak | ArmorType::CursedCloak | ArmorType::SelectCloak | ArmorType::SpiritCuirass | ArmorType::RevivalCuriass | ArmorType::AllianceUniform | ArmorType::OfficerUniform | ArmorType::CommanderUniform | ArmorType::CrimsonCoat | ArmorType::InfantryGear | ArmorType::LieutenantGear | ArmorType::InfantryMantle | ArmorType::LieutenantMantle | ArmorType::UnionField | ArmorType::SamuraiArmor | ArmorType::StealthSuit) + matches!( + self.armor, + ArmorType::HunterField + | ArmorType::RangerField + | ArmorType::ForceField + | ArmorType::RevivalGarment + | ArmorType::SpiritGarment + | ArmorType::StinkFrame + | ArmorType::DPartsVer101 + | ArmorType::DPartsVer210 + | ArmorType::ParasiteWearDeRol + | ArmorType::ParasiteWearNelgal + | ArmorType::ParasiteWearVajulla + | ArmorType::SensePlate + | ArmorType::GravitonPlate + | ArmorType::AttributePlate + | ArmorType::FlowensFrame + | ArmorType::CustomFrameVerOo + | ArmorType::DbsArmor + | ArmorType::GuardWave + | ArmorType::DfField + | ArmorType::LuminousField + | ArmorType::ChuChuFever + | ArmorType::LoveHeart + | ArmorType::FlameGarment + | ArmorType::VirusArmorLafuteria + | ArmorType::BrightnessCircle + | ArmorType::AuraField + | ArmorType::ElectroFrame + | ArmorType::SacredCloth + | ArmorType::SmokingPlate + | ArmorType::StarCuirass + | ArmorType::BlackHoundCuirass + | ArmorType::MorningPrayer + | ArmorType::BlackOdoshiDomaru + | ArmorType::RedOdoshiDomaru + | ArmorType::BlackOdoshiRedNimaidou + | ArmorType::BlueOdoshiVioletNimaidou + | ArmorType::DirtyLifejacket + | ArmorType::KroesSweater + | ArmorType::WeddingDress + | ArmorType::SonicteamArmor + | ArmorType::RedCoat + | ArmorType::Thirteen + | ArmorType::MotherGarb + | ArmorType::MotherGarbPlus + | ArmorType::DressPlate + | ArmorType::Sweetheart + | ArmorType::IgnitionCloak + | ArmorType::CongealCloak + | ArmorType::TempestCloak + | ArmorType::CursedCloak + | ArmorType::SelectCloak + | ArmorType::SpiritCuirass + | ArmorType::RevivalCuriass + | ArmorType::AllianceUniform + | ArmorType::OfficerUniform + | ArmorType::CommanderUniform + | ArmorType::CrimsonCoat + | ArmorType::InfantryGear + | ArmorType::LieutenantGear + | ArmorType::InfantryMantle + | ArmorType::LieutenantMantle + | ArmorType::UnionField + | ArmorType::SamuraiArmor + | ArmorType::StealthSuit + ) } } -- 2.36.0 From c417390aeb5b79cb99b99e9c7ef19865d69c9893 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 02:23:45 +0000 Subject: [PATCH 05/34] rustfmt mag.rs --- src/entity/item/mag.rs | 44 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/entity/item/mag.rs b/src/entity/item/mag.rs index e7a6d70..087ee88 100644 --- a/src/entity/item/mag.rs +++ b/src/entity/item/mag.rs @@ -1101,7 +1101,49 @@ impl Mag { // TODO: is this even needed? mags are not shop sellable...yet pub fn is_rare_item(self) -> bool { - matches!(self.mag, MagType::Pitri | MagType::Soniti | MagType::Preta | MagType::Churel | MagType::Robochao | MagType::OpaOpa | MagType::Pian | MagType::Chao | MagType::ChuChu | MagType::KapuKapu | MagType::AngelsWing | MagType::DevilsWing | MagType::Elenor | MagType::MarkIII | MagType::MasterSystem | MagType::Genesis | MagType::SegaSaturn | MagType::Dreamcast | MagType::Hamburger | MagType::PanzersTail | MagType::DevilsTail | MagType::Deva | MagType::Rati | MagType::Savitri | MagType::Rukmin | MagType::Pushan | MagType::Diwari | MagType::Sato | MagType::Bhima | MagType::Nidra | MagType::GeungSi | MagType::Tellusis | MagType::StrikerUnit | MagType::Pioneer | MagType::Puyo | MagType::Moro | MagType::Rappy | MagType::Yahoo | MagType::GaelGiel | MagType::Agastya) + matches!( + self.mag, + MagType::Pitri + | MagType::Soniti + | MagType::Preta + | MagType::Churel + | MagType::Robochao + | MagType::OpaOpa + | MagType::Pian + | MagType::Chao + | MagType::ChuChu + | MagType::KapuKapu + | MagType::AngelsWing + | MagType::DevilsWing + | MagType::Elenor + | MagType::MarkIII + | MagType::MasterSystem + | MagType::Genesis + | MagType::SegaSaturn + | MagType::Dreamcast + | MagType::Hamburger + | MagType::PanzersTail + | MagType::DevilsTail + | MagType::Deva + | MagType::Rati + | MagType::Savitri + | MagType::Rukmin + | MagType::Pushan + | MagType::Diwari + | MagType::Sato + | MagType::Bhima + | MagType::Nidra + | MagType::GeungSi + | MagType::Tellusis + | MagType::StrikerUnit + | MagType::Pioneer + | MagType::Puyo + | MagType::Moro + | MagType::Rappy + | MagType::Yahoo + | MagType::GaelGiel + | MagType::Agastya + ) } } -- 2.36.0 From e974285e4bc2054db0db27308d538dcd199f7c13 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 02:27:12 +0000 Subject: [PATCH 06/34] rustfmt shield.rs --- src/entity/item/shield.rs | 148 +++++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 1 deletion(-) diff --git a/src/entity/item/shield.rs b/src/entity/item/shield.rs index 40faf4e..5c42598 100644 --- a/src/entity/item/shield.rs +++ b/src/entity/item/shield.rs @@ -550,6 +550,152 @@ impl Shield { } pub fn is_rare_item(self) -> bool { - matches!(self.shield, ShieldType::InvisibleGuard | ShieldType::SacredGuard | ShieldType::SPartsVer116 | ShieldType::SPartsVer201 | ShieldType::LightRelief | ShieldType::ShieldOfDelsaber | ShieldType::ForceWall | ShieldType::RangerWall | ShieldType::HunterWall | ShieldType::AttributeWall | ShieldType::SecretGear | ShieldType::CombatGear | ShieldType::ProtoRegeneGear | ShieldType::RegenerateGear | ShieldType::RegeneGearAdv | ShieldType::FlowensShield | ShieldType::CustomBarrierVerOo | ShieldType::DbsShield | ShieldType::RedRing | ShieldType::TripolicShield | ShieldType::StandstillShield | ShieldType::SafetyHeart | ShieldType::KasamiBracer | ShieldType::GodsShieldSuzaku | ShieldType::GodsShieldGenbu | ShieldType::GodsShieldByakko | ShieldType::GodsShieldSeiryu | ShieldType::HuntersShell | ShieldType::RicosGlasses | ShieldType::RicosEarring | ShieldType::BlueRing | ShieldType::Barrier2 | ShieldType::SecureFeet | ShieldType::Barrier3 | ShieldType::Barrier4 | ShieldType::Barrier5 | ShieldType::Barrier6 | ShieldType::RestaMerge | ShieldType::AntiMerge | ShieldType::ShiftaMerge | ShieldType::DebandMerge | ShieldType::FoieMerge | ShieldType::GifoieMerge | ShieldType::RafoieMerge | ShieldType::RedMerge | ShieldType::BartaMerge | ShieldType::GibartaMerge | ShieldType::RabartaMerge | ShieldType::BlueMerge | ShieldType::ZondeMerge | ShieldType::GizondeMerge | ShieldType::RazondeMerge | ShieldType::YellowMerge | ShieldType::RecoveryBarrier | ShieldType::AssistBarrier | ShieldType::RedBarrier | ShieldType::BlueBarrier | ShieldType::YellowBarrier | ShieldType::WeaponsGoldShield | ShieldType::BlackGear | ShieldType::WorksGuard | ShieldType::RagolRing | ShieldType::BlueRing2 | ShieldType::BlueRing3 | ShieldType::BlueRing4 | ShieldType::BlueRing5 | ShieldType::BlueRing6 | ShieldType::BlueRing7 | ShieldType::BlueRing8 | ShieldType::BlueRing9 | ShieldType::GreenRing | ShieldType::GreenRing2 | ShieldType::GreenRing3 | ShieldType::GreenRing4 | ShieldType::GreenRing5 | ShieldType::GreenRing6 | ShieldType::GreenRing7 | ShieldType::GreenRing8 | ShieldType::YellowRing | ShieldType::YellowRing2 | ShieldType::YellowRing3 | ShieldType::YellowRing4 | ShieldType::YellowRing5 | ShieldType::YellowRing6 | ShieldType::YellowRing7 | ShieldType::YellowRing8 | ShieldType::PurpleRing | ShieldType::PurpleRing2 | ShieldType::PurpleRing3 | ShieldType::PurpleRing4 | ShieldType::PurpleRing5 | ShieldType::PurpleRing6 | ShieldType::PurpleRing7 | ShieldType::PurpleRing8 | ShieldType::WhiteRing | ShieldType::WhiteRing2 | ShieldType::WhiteRing3 | ShieldType::WhiteRing4 | ShieldType::WhiteRing5 | ShieldType::WhiteRing6 | ShieldType::WhiteRing7 | ShieldType::WhiteRing8 | ShieldType::BlackRing | ShieldType::BlackRing2 | ShieldType::BlackRing3 | ShieldType::BlackRing4 | ShieldType::BlackRing5 | ShieldType::BlackRing6 | ShieldType::BlackRing7 | ShieldType::BlackRing8 | ShieldType::WeaponsSilverShield | ShieldType::WeaponsCopperShield | ShieldType::Gratia | ShieldType::TripolicReflector | ShieldType::StrikerPlus | ShieldType::RegenerateGearBP | ShieldType::Rupika | ShieldType::YataMirror | ShieldType::BunnyEars | ShieldType::CatEars | ShieldType::ThreeSeals | ShieldType::GodsShieldKouryu | ShieldType::DfShield | ShieldType::FromTheDepths | ShieldType::DeRolLeShield | ShieldType::HoneycombReflector | ShieldType::Epsiguard | ShieldType::AngelRing | ShieldType::UnionGuard | ShieldType::UnionGuard2 | ShieldType::UnionGuard3 | ShieldType::UnionGuard4 | ShieldType::StinkShield | ShieldType::Unknownb | ShieldType::Genpei | ShieldType::Genpei2 | ShieldType::Genpei3 | ShieldType::Genpei4 | ShieldType::Genpei5 | ShieldType::Genpei6 | ShieldType::Genpei7 | ShieldType::Genpei8 | ShieldType::Genpei9 | ShieldType::Genpei10) + matches!( + self.shield, + ShieldType::InvisibleGuard + | ShieldType::SacredGuard + | ShieldType::SPartsVer116 + | ShieldType::SPartsVer201 + | ShieldType::LightRelief + | ShieldType::ShieldOfDelsaber + | ShieldType::ForceWall + | ShieldType::RangerWall + | ShieldType::HunterWall + | ShieldType::AttributeWall + | ShieldType::SecretGear + | ShieldType::CombatGear + | ShieldType::ProtoRegeneGear + | ShieldType::RegenerateGear + | ShieldType::RegeneGearAdv + | ShieldType::FlowensShield + | ShieldType::CustomBarrierVerOo + | ShieldType::DbsShield + | ShieldType::RedRing + | ShieldType::TripolicShield + | ShieldType::StandstillShield + | ShieldType::SafetyHeart + | ShieldType::KasamiBracer + | ShieldType::GodsShieldSuzaku + | ShieldType::GodsShieldGenbu + | ShieldType::GodsShieldByakko + | ShieldType::GodsShieldSeiryu + | ShieldType::HuntersShell + | ShieldType::RicosGlasses + | ShieldType::RicosEarring + | ShieldType::BlueRing + | ShieldType::Barrier2 + | ShieldType::SecureFeet + | ShieldType::Barrier3 + | ShieldType::Barrier4 + | ShieldType::Barrier5 + | ShieldType::Barrier6 + | ShieldType::RestaMerge + | ShieldType::AntiMerge + | ShieldType::ShiftaMerge + | ShieldType::DebandMerge + | ShieldType::FoieMerge + | ShieldType::GifoieMerge + | ShieldType::RafoieMerge + | ShieldType::RedMerge + | ShieldType::BartaMerge + | ShieldType::GibartaMerge + | ShieldType::RabartaMerge + | ShieldType::BlueMerge + | ShieldType::ZondeMerge + | ShieldType::GizondeMerge + | ShieldType::RazondeMerge + | ShieldType::YellowMerge + | ShieldType::RecoveryBarrier + | ShieldType::AssistBarrier + | ShieldType::RedBarrier + | ShieldType::BlueBarrier + | ShieldType::YellowBarrier + | ShieldType::WeaponsGoldShield + | ShieldType::BlackGear + | ShieldType::WorksGuard + | ShieldType::RagolRing + | ShieldType::BlueRing2 + | ShieldType::BlueRing3 + | ShieldType::BlueRing4 + | ShieldType::BlueRing5 + | ShieldType::BlueRing6 + | ShieldType::BlueRing7 + | ShieldType::BlueRing8 + | ShieldType::BlueRing9 + | ShieldType::GreenRing + | ShieldType::GreenRing2 + | ShieldType::GreenRing3 + | ShieldType::GreenRing4 + | ShieldType::GreenRing5 + | ShieldType::GreenRing6 + | ShieldType::GreenRing7 + | ShieldType::GreenRing8 + | ShieldType::YellowRing + | ShieldType::YellowRing2 + | ShieldType::YellowRing3 + | ShieldType::YellowRing4 + | ShieldType::YellowRing5 + | ShieldType::YellowRing6 + | ShieldType::YellowRing7 + | ShieldType::YellowRing8 + | ShieldType::PurpleRing + | ShieldType::PurpleRing2 + | ShieldType::PurpleRing3 + | ShieldType::PurpleRing4 + | ShieldType::PurpleRing5 + | ShieldType::PurpleRing6 + | ShieldType::PurpleRing7 + | ShieldType::PurpleRing8 + | ShieldType::WhiteRing + | ShieldType::WhiteRing2 + | ShieldType::WhiteRing3 + | ShieldType::WhiteRing4 + | ShieldType::WhiteRing5 + | ShieldType::WhiteRing6 + | ShieldType::WhiteRing7 + | ShieldType::WhiteRing8 + | ShieldType::BlackRing + | ShieldType::BlackRing2 + | ShieldType::BlackRing3 + | ShieldType::BlackRing4 + | ShieldType::BlackRing5 + | ShieldType::BlackRing6 + | ShieldType::BlackRing7 + | ShieldType::BlackRing8 + | ShieldType::WeaponsSilverShield + | ShieldType::WeaponsCopperShield + | ShieldType::Gratia + | ShieldType::TripolicReflector + | ShieldType::StrikerPlus + | ShieldType::RegenerateGearBP + | ShieldType::Rupika + | ShieldType::YataMirror + | ShieldType::BunnyEars + | ShieldType::CatEars + | ShieldType::ThreeSeals + | ShieldType::GodsShieldKouryu + | ShieldType::DfShield + | ShieldType::FromTheDepths + | ShieldType::DeRolLeShield + | ShieldType::HoneycombReflector + | ShieldType::Epsiguard + | ShieldType::AngelRing + | ShieldType::UnionGuard + | ShieldType::UnionGuard2 + | ShieldType::UnionGuard3 + | ShieldType::UnionGuard4 + | ShieldType::StinkShield + | ShieldType::Unknownb + | ShieldType::Genpei + | ShieldType::Genpei2 + | ShieldType::Genpei3 + | ShieldType::Genpei4 + | ShieldType::Genpei5 + | ShieldType::Genpei6 + | ShieldType::Genpei7 + | ShieldType::Genpei8 + | ShieldType::Genpei9 + | ShieldType::Genpei10 + ) } } -- 2.36.0 From b601f8b4fc4892cfff562589c2866162b6875928 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 02:29:57 +0000 Subject: [PATCH 07/34] rustfmt tool.rs --- src/entity/item/tool.rs | 165 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 163 insertions(+), 2 deletions(-) diff --git a/src/entity/item/tool.rs b/src/entity/item/tool.rs index 0fd2167..f24f596 100644 --- a/src/entity/item/tool.rs +++ b/src/entity/item/tool.rs @@ -682,11 +682,172 @@ impl Tool { } pub fn is_rare_item(self) -> bool { - matches!(self.tool, ToolType::CellOfMag502 | ToolType::CellOfMag213 | ToolType::PartsOfRobochao | ToolType::HeartOfOpaOpa | ToolType::HeartOfPian | ToolType::HeartOfChao | ToolType::SorcerersRightArm | ToolType::SBeatsArms | ToolType::PArmsArms | ToolType::DelsabersRightArm | ToolType::BringersRightArm | ToolType::DelsabersLeftArm | ToolType::SRedsArms | ToolType::DragonsClaw | ToolType::HildebearsHead | ToolType::HildebluesHead | ToolType::PartsOfBaranz | ToolType::BelrasRightArm | ToolType::GiGuesBody | ToolType::SinowBerillsArms | ToolType::GrassAssassinsArms | ToolType::BoomasRightArm | ToolType::GoboomasRightArm | ToolType::GigoboomasRightArm | ToolType::GalGryphonsWing | ToolType::RappysWing | ToolType::CladdingOfEpsilon | ToolType::DeRolLeShell | ToolType::BerillPhoton | ToolType::ParasiticGeneFlow | ToolType::MagicStoneIritista | ToolType::BlueBlackStone | ToolType::Syncesta | ToolType::MagicWater | ToolType::ParasiticCellTypeD | ToolType::MagicRockHeartKey | ToolType::MagicRockMoola | ToolType::StarAmplifier | ToolType::BookOfHitogata | ToolType::HeartOfChuChu | ToolType::PartsOfEggBlaster | ToolType::HeartOfAngel | ToolType::HeartOfDevil | ToolType::KitOfHamburger | ToolType::PanthersSpirit | ToolType::KitOfMark3 | ToolType::KitOfMasterSystem | ToolType::KitOfGenesis | ToolType::KitOfSegaSaturn | ToolType::KitOfDreamcast | ToolType::AmplifierOfResta | ToolType::AmplifierOfAnti | ToolType::AmplifierOfShifta | ToolType::AmplifierOfDeband | ToolType::AmplifierOfFoie | ToolType::AmplifierOfGifoie | ToolType::AmplifierOfRafoie | ToolType::AmplifierOfBarta | ToolType::AmplifierOfGibarta | ToolType::AmplifierOfRabarta | ToolType::AmplifierOfZonde | ToolType::AmplifierOfGizonde | ToolType::AmplifierOfRazonde | ToolType::AmplifierOfRed | ToolType::AmplifierOfBlue | ToolType::AmplifierOfYellow | ToolType::HeartOfKapuKapu | ToolType::PhotonBooster | ToolType::Addslot | ToolType::PhotonDrop | ToolType::PhotonSphere | ToolType::PhotonCrystal | ToolType::SecretTicket | ToolType::PhotonTicket | ToolType::BookOfKatana1 | ToolType::BookOfKatana2 | ToolType::BookOfKatana3 | ToolType::WeaponsBronzeBadge | ToolType::WeaponsSilverBadge | ToolType::WeaponsGoldBadge | ToolType::WeaponsCrystalBadge | ToolType::WeaponsSteelBadge | ToolType::WeaponsAluminumBadge | ToolType::WeaponsLeatherBadge | ToolType::WeaponsBoneBadge | ToolType::LetterOfAppreciation | ToolType::ItemTicket | ToolType::ValentinesChocolate | ToolType::NewYearsCard | ToolType::ChristmasCard | ToolType::BirthdayCard | ToolType::ProofOfSonicTeam | ToolType::SpecialEventTicket | ToolType::FlowerBouquet | ToolType::Cake | ToolType::Accessories | ToolType::MrNakasBusinessCard | ToolType::Present | ToolType::Chocolate | ToolType::Candy | ToolType::Cake2 | ToolType::WeaponsSilverBadge2 | ToolType::WeaponsGoldBadge2 | ToolType::WeaponsCrystalBadge2 | ToolType::WeaponsSteelBadge2 | ToolType::WeaponsAluminumBadge2 | ToolType::WeaponsLeatherBadge2 | ToolType::WeaponsBoneBadge2 | ToolType::Bouquet | ToolType::Decoction | ToolType::ChristmasPresent | ToolType::EasterEgg | ToolType::JackOLantern | ToolType::DiskVol1WeddingMarch | ToolType::DiskVol2DayLight | ToolType::DiskVol3BurningRangers | ToolType::DiskVol4OpenYourHeart | ToolType::DiskVol5LiveLearn | ToolType::DiskVol6Nights | ToolType::DiskVol7EndingThemePianoVer | ToolType::DiskVol8HeartToHeart | ToolType::DiskVol9StrangeBlue | ToolType::DiskVol10ReunionSystem | ToolType::DiskVol11Pinnacles | ToolType::DiskVol12FightInsideTheSpaceship | ToolType::HuntersReport | ToolType::HuntersReport2 | ToolType::HuntersReport3 | ToolType::HuntersReport4 | ToolType::HuntersReport5 | ToolType::Tablet | ToolType::Unknown2 | ToolType::DragonScale | ToolType::HeavenStrikerCoat | ToolType::PioneerParts | ToolType::AmitiesMemo | ToolType::HeartOfMorolian | ToolType::RappysBeak | ToolType::YahoosEngine | ToolType::DPhotonCore | ToolType::LibertaKit | ToolType::CellOfMag0503 | ToolType::CellOfMag0504 | ToolType::CellOfMag0505 | ToolType::CellOfMag0506 | ToolType::CellOfMag0507 | ToolType::TeamPoints500 | ToolType::TeamPoints1000 | ToolType::TeamPoints5000 | ToolType::TeamPoints10000) + matches!( + self.tool, + ToolType::CellOfMag502 + | ToolType::CellOfMag213 + | ToolType::PartsOfRobochao + | ToolType::HeartOfOpaOpa + | ToolType::HeartOfPian + | ToolType::HeartOfChao + | ToolType::SorcerersRightArm + | ToolType::SBeatsArms + | ToolType::PArmsArms + | ToolType::DelsabersRightArm + | ToolType::BringersRightArm + | ToolType::DelsabersLeftArm + | ToolType::SRedsArms + | ToolType::DragonsClaw + | ToolType::HildebearsHead + | ToolType::HildebluesHead + | ToolType::PartsOfBaranz + | ToolType::BelrasRightArm + | ToolType::GiGuesBody + | ToolType::SinowBerillsArms + | ToolType::GrassAssassinsArms + | ToolType::BoomasRightArm + | ToolType::GoboomasRightArm + | ToolType::GigoboomasRightArm + | ToolType::GalGryphonsWing + | ToolType::RappysWing + | ToolType::CladdingOfEpsilon + | ToolType::DeRolLeShell + | ToolType::BerillPhoton + | ToolType::ParasiticGeneFlow + | ToolType::MagicStoneIritista + | ToolType::BlueBlackStone + | ToolType::Syncesta + | ToolType::MagicWater + | ToolType::ParasiticCellTypeD + | ToolType::MagicRockHeartKey + | ToolType::MagicRockMoola + | ToolType::StarAmplifier + | ToolType::BookOfHitogata + | ToolType::HeartOfChuChu + | ToolType::PartsOfEggBlaster + | ToolType::HeartOfAngel + | ToolType::HeartOfDevil + | ToolType::KitOfHamburger + | ToolType::PanthersSpirit + | ToolType::KitOfMark3 + | ToolType::KitOfMasterSystem + | ToolType::KitOfGenesis + | ToolType::KitOfSegaSaturn + | ToolType::KitOfDreamcast + | ToolType::AmplifierOfResta + | ToolType::AmplifierOfAnti + | ToolType::AmplifierOfShifta + | ToolType::AmplifierOfDeband + | ToolType::AmplifierOfFoie + | ToolType::AmplifierOfGifoie + | ToolType::AmplifierOfRafoie + | ToolType::AmplifierOfBarta + | ToolType::AmplifierOfGibarta + | ToolType::AmplifierOfRabarta + | ToolType::AmplifierOfZonde + | ToolType::AmplifierOfGizonde + | ToolType::AmplifierOfRazonde + | ToolType::AmplifierOfRed + | ToolType::AmplifierOfBlue + | ToolType::AmplifierOfYellow + | ToolType::HeartOfKapuKapu + | ToolType::PhotonBooster + | ToolType::Addslot + | ToolType::PhotonDrop + | ToolType::PhotonSphere + | ToolType::PhotonCrystal + | ToolType::SecretTicket + | ToolType::PhotonTicket + | ToolType::BookOfKatana1 + | ToolType::BookOfKatana2 + | ToolType::BookOfKatana3 + | ToolType::WeaponsBronzeBadge + | ToolType::WeaponsSilverBadge + | ToolType::WeaponsGoldBadge + | ToolType::WeaponsCrystalBadge + | ToolType::WeaponsSteelBadge + | ToolType::WeaponsAluminumBadge + | ToolType::WeaponsLeatherBadge + | ToolType::WeaponsBoneBadge + | ToolType::LetterOfAppreciation + | ToolType::ItemTicket + | ToolType::ValentinesChocolate + | ToolType::NewYearsCard + | ToolType::ChristmasCard + | ToolType::BirthdayCard + | ToolType::ProofOfSonicTeam + | ToolType::SpecialEventTicket + | ToolType::FlowerBouquet + | ToolType::Cake + | ToolType::Accessories + | ToolType::MrNakasBusinessCard + | ToolType::Present + | ToolType::Chocolate + | ToolType::Candy + | ToolType::Cake2 + | ToolType::WeaponsSilverBadge2 + | ToolType::WeaponsGoldBadge2 + | ToolType::WeaponsCrystalBadge2 + | ToolType::WeaponsSteelBadge2 + | ToolType::WeaponsAluminumBadge2 + | ToolType::WeaponsLeatherBadge2 + | ToolType::WeaponsBoneBadge2 + | ToolType::Bouquet + | ToolType::Decoction + | ToolType::ChristmasPresent + | ToolType::EasterEgg + | ToolType::JackOLantern + | ToolType::DiskVol1WeddingMarch + | ToolType::DiskVol2DayLight + | ToolType::DiskVol3BurningRangers + | ToolType::DiskVol4OpenYourHeart + | ToolType::DiskVol5LiveLearn + | ToolType::DiskVol6Nights + | ToolType::DiskVol7EndingThemePianoVer + | ToolType::DiskVol8HeartToHeart + | ToolType::DiskVol9StrangeBlue + | ToolType::DiskVol10ReunionSystem + | ToolType::DiskVol11Pinnacles + | ToolType::DiskVol12FightInsideTheSpaceship + | ToolType::HuntersReport + | ToolType::HuntersReport2 + | ToolType::HuntersReport3 + | ToolType::HuntersReport4 + | ToolType::HuntersReport5 + | ToolType::Tablet + | ToolType::Unknown2 + | ToolType::DragonScale + | ToolType::HeavenStrikerCoat + | ToolType::PioneerParts + | ToolType::AmitiesMemo + | ToolType::HeartOfMorolian + | ToolType::RappysBeak + | ToolType::YahoosEngine + | ToolType::DPhotonCore + | ToolType::LibertaKit + | ToolType::CellOfMag0503 + | ToolType::CellOfMag0504 + | ToolType::CellOfMag0505 + | ToolType::CellOfMag0506 + | ToolType::CellOfMag0507 + | ToolType::TeamPoints500 + | ToolType::TeamPoints1000 + | ToolType::TeamPoints5000 + | ToolType::TeamPoints10000 + ) } // TODO: do we actually need this function? pub fn is_material(self) -> bool { - matches!(self.tool, ToolType::PowerMaterial | ToolType::MindMaterial | ToolType::EvadeMaterial | ToolType::HpMaterial | ToolType::TpMaterial | ToolType::DefMaterial | ToolType::LuckMaterial) + matches!( + self.tool, + ToolType::PowerMaterial + | ToolType::MindMaterial + | ToolType::EvadeMaterial + | ToolType::HpMaterial + | ToolType::TpMaterial + | ToolType::DefMaterial + | ToolType::LuckMaterial + ) } } -- 2.36.0 From b6e1fee5a438bbaad18e540ac6f96110e8395faf Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 02:31:24 +0000 Subject: [PATCH 08/34] rustfmt unit.rs --- src/entity/item/unit.rs | 60 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/entity/item/unit.rs b/src/entity/item/unit.rs index 31becb0..cc973ed 100644 --- a/src/entity/item/unit.rs +++ b/src/entity/item/unit.rs @@ -386,6 +386,64 @@ impl Unit { } pub fn is_rare_item(self) -> bool { - matches!(self.unit, UnitType::GodPower | UnitType::GodMind | UnitType::GodArm | UnitType::GodLegs | UnitType::GodHp | UnitType::GodTp | UnitType::GodBody | UnitType::GodLuck | UnitType::HeroAbility | UnitType::GodAbility | UnitType::AllResist | UnitType::SuperResist | UnitType::PerfectResist | UnitType::HpRevival | UnitType::TpRevival | UnitType::PbAmplifier | UnitType::PbGenerate | UnitType::PbCreate | UnitType::DevilTechnique | UnitType::GodTechnique | UnitType::DevilBattle | UnitType::GodBattle | UnitType::CurePoison | UnitType::CureParalysis | UnitType::CureSlow | UnitType::CureConfuse | UnitType::CureFreeze | UnitType::CureShock | UnitType::YasakaniMagatama | UnitType::V101 | UnitType::V501 | UnitType::V502 | UnitType::V801 | UnitType::Limiter | UnitType::Adept | UnitType::SwordsmanLore | UnitType::ProofOfSwordSaint | UnitType::Smartlink | UnitType::DivineProtection | UnitType::HeavenlyBattle | UnitType::HeavenlyPower | UnitType::HeavenlyMind | UnitType::HeavenlyArms | UnitType::HeavenlyLegs | UnitType::HeavenlyBody | UnitType::HeavenlyLuck | UnitType::HeavenlyAbility | UnitType::CenturionAbility | UnitType::FriendRing | UnitType::HeavenlyHp | UnitType::HeavenlyTp | UnitType::HeavenlyResist | UnitType::HeavenlyTechnique | UnitType::HpRessurection | UnitType::TpRessurection | UnitType::PbIncrease) + matches!( + self.unit, + UnitType::GodPower + | UnitType::GodMind + | UnitType::GodArm + | UnitType::GodLegs + | UnitType::GodHp + | UnitType::GodTp + | UnitType::GodBody + | UnitType::GodLuck + | UnitType::HeroAbility + | UnitType::GodAbility + | UnitType::AllResist + | UnitType::SuperResist + | UnitType::PerfectResist + | UnitType::HpRevival + | UnitType::TpRevival + | UnitType::PbAmplifier + | UnitType::PbGenerate + | UnitType::PbCreate + | UnitType::DevilTechnique + | UnitType::GodTechnique + | UnitType::DevilBattle + | UnitType::GodBattle + | UnitType::CurePoison + | UnitType::CureParalysis + | UnitType::CureSlow + | UnitType::CureConfuse + | UnitType::CureFreeze + | UnitType::CureShock + | UnitType::YasakaniMagatama + | UnitType::V101 + | UnitType::V501 + | UnitType::V502 + | UnitType::V801 + | UnitType::Limiter + | UnitType::Adept + | UnitType::SwordsmanLore + | UnitType::ProofOfSwordSaint + | UnitType::Smartlink + | UnitType::DivineProtection + | UnitType::HeavenlyBattle + | UnitType::HeavenlyPower + | UnitType::HeavenlyMind + | UnitType::HeavenlyArms + | UnitType::HeavenlyLegs + | UnitType::HeavenlyBody + | UnitType::HeavenlyLuck + | UnitType::HeavenlyAbility + | UnitType::CenturionAbility + | UnitType::FriendRing + | UnitType::HeavenlyHp + | UnitType::HeavenlyTp + | UnitType::HeavenlyResist + | UnitType::HeavenlyTechnique + | UnitType::HpRessurection + | UnitType::TpRessurection + | UnitType::PbIncrease + ) } } -- 2.36.0 From d59e0691d74c56df54870a1a2c455350ae437cb8 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 02:32:49 +0000 Subject: [PATCH 09/34] rustfmt weapon.rs --- src/entity/item/weapon.rs | 63 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/src/entity/item/weapon.rs b/src/entity/item/weapon.rs index d07e34d..9f4ea27 100644 --- a/src/entity/item/weapon.rs +++ b/src/entity/item/weapon.rs @@ -1587,8 +1587,65 @@ impl Weapon { // TODO: invert this? ie: handgun, saber, dagger etc. => false, _ => true? pub fn is_rare_item(self) -> bool { - !matches!(self.weapon, WeaponType::Saber | WeaponType::Brand | WeaponType::Buster | WeaponType::Pallasch | WeaponType::Gladius | WeaponType::Sword | WeaponType::Gigush | WeaponType::Breaker | WeaponType::Claymore | WeaponType::Calibur | WeaponType::Dagger | WeaponType::Knife | WeaponType::Blade | WeaponType::Edge | WeaponType::Ripper | WeaponType::Partisan | WeaponType::Halbert | WeaponType::Glaive | WeaponType::Berdys | WeaponType::Gungnir | WeaponType::Slicer | WeaponType::Spinner | WeaponType::Cutter | WeaponType::Sawcer | WeaponType::Diska | WeaponType::Handgun | WeaponType::Autogun | WeaponType::Lockgun | WeaponType::Railgun | WeaponType::Raygun | WeaponType::Rifle | WeaponType::Sniper | WeaponType::Blaster | WeaponType::Beam | WeaponType::Laser | WeaponType::Mechgun | WeaponType::Assault | WeaponType::Repeater | WeaponType::Gatling | WeaponType::Vulcan | WeaponType::Shot | WeaponType::Spread | WeaponType::Cannon | WeaponType::Launcher | WeaponType::Arms | WeaponType::Cane | WeaponType::Stick | WeaponType::Mace | WeaponType::Club | WeaponType::Rod | WeaponType::Pole | WeaponType::Pillar | WeaponType::Striker | WeaponType::Wand | WeaponType::Staff | WeaponType::Baton | WeaponType::Scepter) + !matches!( + self.weapon, + WeaponType::Saber + | WeaponType::Brand + | WeaponType::Buster + | WeaponType::Pallasch + | WeaponType::Gladius + | WeaponType::Sword + | WeaponType::Gigush + | WeaponType::Breaker + | WeaponType::Claymore + | WeaponType::Calibur + | WeaponType::Dagger + | WeaponType::Knife + | WeaponType::Blade + | WeaponType::Edge + | WeaponType::Ripper + | WeaponType::Partisan + | WeaponType::Halbert + | WeaponType::Glaive + | WeaponType::Berdys + | WeaponType::Gungnir + | WeaponType::Slicer + | WeaponType::Spinner + | WeaponType::Cutter + | WeaponType::Sawcer + | WeaponType::Diska + | WeaponType::Handgun + | WeaponType::Autogun + | WeaponType::Lockgun + | WeaponType::Railgun + | WeaponType::Raygun + | WeaponType::Rifle + | WeaponType::Sniper + | WeaponType::Blaster + | WeaponType::Beam + | WeaponType::Laser + | WeaponType::Mechgun + | WeaponType::Assault + | WeaponType::Repeater + | WeaponType::Gatling + | WeaponType::Vulcan + | WeaponType::Shot + | WeaponType::Spread + | WeaponType::Cannon + | WeaponType::Launcher + | WeaponType::Arms + | WeaponType::Cane + | WeaponType::Stick + | WeaponType::Mace + | WeaponType::Club + | WeaponType::Rod + | WeaponType::Pole + | WeaponType::Pillar + | WeaponType::Striker + | WeaponType::Wand + | WeaponType::Staff + | WeaponType::Baton + | WeaponType::Scepter + ) } } - - -- 2.36.0 From 9db4c9cc44e3e26a469f8b6f04316f8e1fe715b8 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 13:31:32 +0000 Subject: [PATCH 10/34] add 3 attr weap sell test --- tests/test_shops.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/tests/test_shops.rs b/tests/test_shops.rs index 1838414..10a4df6 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -259,7 +259,51 @@ async fn test_player_buys_from_armor_shop() { } #[async_std::test] -async fn test_player_sells_to_shop() { +async fn test_player_sells_3_attr_weapon_to_shop() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Weapon( + item::weapon::Weapon { + weapon: item::weapon::WeaponType::Vulcan, + grind: 5, + special: Some(item::weapon::WeaponSpecial::Charge), + attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}), + Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}), + Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Native, value: 100}),], + tekked: true, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 4406); } #[async_std::test] -- 2.36.0 From fbc68c7a26d2e5815e3f754598f16f915d575661 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 17:08:55 +0000 Subject: [PATCH 11/34] handle selling photon tools and untekked weapon test --- src/ship/items/inventory.rs | 8 ++++--- tests/test_shops.rs | 48 +++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/ship/items/inventory.rs b/src/ship/items/inventory.rs index 7de42e9..4ff2992 100644 --- a/src/ship/items/inventory.rs +++ b/src/ship/items/inventory.rs @@ -3,7 +3,7 @@ use thiserror::Error; use libpso::character::character; use crate::entity::character::CharacterEntityId; use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, ItemType, ItemLocation, InventoryEntity, InventoryItemEntity, EquippedEntity}; -use crate::entity::item::tool::Tool; +use crate::entity::item::tool::{Tool, ToolType}; use crate::entity::item::mag::Mag; use crate::entity::item::weapon::Weapon; use crate::ship::items::{ClientItemId, BankItem, BankItemHandle}; @@ -256,8 +256,10 @@ impl InventoryItem { Some((ArmorShopItem::unit_from_item(u).price() / 8) as u32) }, ItemDetail::Tool(t) => { - if t.is_rare_item() { // TODO: photon drop/sphere etc - return Some(10u32) + if !matches!(t.tool, ToolType::PhotonDrop | ToolType::PhotonSphere | ToolType::PhotonCrystal) { + if t.is_rare_item() { + return Some(10u32) + } } Some((ToolShopItem::tool_from_item(t).price() / 8) as u32) }, diff --git a/tests/test_shops.rs b/tests/test_shops.rs index 10a4df6..7cb06c2 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -627,3 +627,51 @@ async fn test_units_disappear_from_shop_when_bought() { }).unwrap(); }).unwrap(); } + +#[async_std::test] +async fn test_selling_untekked_weapon() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Weapon( + item::weapon::Weapon { + weapon: item::weapon::WeaponType::Vulcan, + grind: 5, + special: Some(item::weapon::WeaponSpecial::Charge), + attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}), + Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}), + Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Native, value: 100}),], + tekked: false, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 1); +} \ No newline at end of file -- 2.36.0 From d84b2fc663e56533454dce583388faae3531507a Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 18:29:37 +0000 Subject: [PATCH 12/34] more selling tests --- tests/test_shops.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/tests/test_shops.rs b/tests/test_shops.rs index 7cb06c2..831109c 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -674,4 +674,99 @@ async fn test_selling_untekked_weapon() { let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert_eq!(c1.meseta, 1); +} + +#[async_std::test] +async fn test_player_sells_rare_item() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Weapon( + item::weapon::Weapon { + weapon: item::weapon::WeaponType::DarkFlow, + grind: 5, + special: None, + attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}), + Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}), + Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Native, value: 100}),], + tekked: true, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 10); +} + +#[async_std::test] +async fn test_player_sells_photon_drops() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + let mut photon_drops = Vec::new(); + for _ in 0..7usize { + photon_drops.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Tool( + item::tool::Tool { + tool: item::tool::ToolType::PhotonDrop, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + } + + p1_inv.push(item::InventoryItemEntity::Stacked(photon_drops)); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 3, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 3000); } \ No newline at end of file -- 2.36.0 From 1eff61629a8f0a732c2f3ecb4df40f3e377e5f34 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 21 Jun 2021 18:32:02 +0000 Subject: [PATCH 13/34] andy vs. clippy round 2 --- src/ship/items/inventory.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ship/items/inventory.rs b/src/ship/items/inventory.rs index 4ff2992..dac1ef9 100644 --- a/src/ship/items/inventory.rs +++ b/src/ship/items/inventory.rs @@ -256,10 +256,8 @@ impl InventoryItem { Some((ArmorShopItem::unit_from_item(u).price() / 8) as u32) }, ItemDetail::Tool(t) => { - if !matches!(t.tool, ToolType::PhotonDrop | ToolType::PhotonSphere | ToolType::PhotonCrystal) { - if t.is_rare_item() { - return Some(10u32) - } + if !matches!(t.tool, ToolType::PhotonDrop | ToolType::PhotonSphere | ToolType::PhotonCrystal) && t.is_rare_item() { + return Some(10u32) } Some((ToolShopItem::tool_from_item(t).price() / 8) as u32) }, -- 2.36.0 From 61e7e8b39f641cf6a196c52b93160af24f0ed67a Mon Sep 17 00:00:00 2001 From: andy Date: Sat, 31 Jul 2021 01:28:30 +0000 Subject: [PATCH 14/34] add impl From<> for shops. get_sell_price returns Result now. --- src/ship/items/inventory.rs | 50 ++++++++++++++++++++++++------------- src/ship/items/manager.rs | 7 +++--- src/ship/shops/armor.rs | 34 +++++++++++++++++++------ src/ship/shops/tool.rs | 22 ++++++++++++---- src/ship/shops/weapon.rs | 11 ++++++++ 5 files changed, 90 insertions(+), 34 deletions(-) diff --git a/src/ship/items/inventory.rs b/src/ship/items/inventory.rs index dac1ef9..405db34 100644 --- a/src/ship/items/inventory.rs +++ b/src/ship/items/inventory.rs @@ -6,7 +6,7 @@ use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, ItemType, ItemLo use crate::entity::item::tool::{Tool, ToolType}; use crate::entity::item::mag::Mag; use crate::entity::item::weapon::Weapon; -use crate::ship::items::{ClientItemId, BankItem, BankItemHandle}; +use crate::ship::items::{ClientItemId, BankItem, BankItemHandle, ItemManagerError}; use crate::ship::items::floor::{IndividualFloorItem, StackedFloorItem}; use crate::ship::shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem}; @@ -222,59 +222,75 @@ impl InventoryItem { } } - pub fn get_sell_price(&self) -> Option { + // pub fn get_sell_price(&self) -> Option { + pub fn get_sell_price(&self) -> Result { match self { InventoryItem::Individual(individual_item) => { match &individual_item.item { // TODO: can wrapped items be sold? ItemDetail::Weapon(w) => { if !w.tekked { - return Some(1u32) + // return Some(1u32) + return Ok(1u32) } if w.is_rare_item() { - return Some(10u32) + // return Some(10u32) + return Ok(10u32) } // other item factors? - Some((WeaponShopItem::weapon_from_item(w).price() / 8) as u32) + // Some((WeaponShopItem::from(w).price() / 8) as u32) + Ok((WeaponShopItem::from(w).price() / 8) as u32) }, ItemDetail::Armor(a) => { if a.is_rare_item() { - return Some(10u32) + // return Some(10u32) + return Ok(10u32) } - Some((ArmorShopItem::armor_from_item(a).price() / 8) as u32) + // Some((ArmorShopItem::from(a).price() / 8) as u32) + return Ok((ArmorShopItem::from(a).price() / 8) as u32) }, ItemDetail::Shield(s) => { if s.is_rare_item() { - return Some(10u32) + // return Some(10u32) + return Ok(10u32) } - Some((ArmorShopItem::shield_from_item(s).price() / 8) as u32) + // Some((ArmorShopItem::from(s).price() / 8) as u32) + return Ok((ArmorShopItem::from(s).price() / 8) as u32) }, ItemDetail::Unit(u) => { if u.is_rare_item() { - return Some(10u32) + // return Some(10u32) + return Ok(10u32) } - Some((ArmorShopItem::unit_from_item(u).price() / 8) as u32) + // Some((ArmorShopItem::from(u).price() / 8) as u32) + return Ok((ArmorShopItem::from(u).price() / 8) as u32) }, ItemDetail::Tool(t) => { if !matches!(t.tool, ToolType::PhotonDrop | ToolType::PhotonSphere | ToolType::PhotonCrystal) && t.is_rare_item() { - return Some(10u32) + // return Some(10u32) + return Ok(10u32) } - Some((ToolShopItem::tool_from_item(t).price() / 8) as u32) + // Some((ToolShopItem::from(t).price() / 8) as u32) + return Ok((ToolShopItem::from(t).price() / 8) as u32) }, ItemDetail::TechniqueDisk(d) => { // TODO: are all techs the same? - Some((ToolShopItem::tech_from_item(d).price() / 8) as u32) + // Some((ToolShopItem::from(d).price() / 8) as u32) + return Ok((ToolShopItem::from(d).price() / 8) as u32) }, ItemDetail::Mag(_m) => { //TODO: error. mags are not sellable - None + // None + return Err(ItemManagerError::ItemNotSellable(self.clone())) }, ItemDetail::ESWeapon(_e) => { - Some(10u32) // TODO: check price + // Some(10u32) // TODO: check price + return Ok(10u32) }, } }, // the number of stacked items sold is handled by the caller. this is just the price of 1 InventoryItem::Stacked(stacked_item) => { - Some((ToolShopItem::tool_from_item(&stacked_item.tool).price() / 8) as u32) + // Some((ToolShopItem::from(&stacked_item.tool).price() / 8) as u32) + return Ok((ToolShopItem::from(&stacked_item.tool).price() / 8) as u32) }, } } diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index 1186dee..9ca85e6 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -56,7 +56,7 @@ pub enum ItemManagerError { NoArmorEquipped, GatewayError(#[from] crate::entity::gateway::GatewayError), StackedItemError(Vec), - ItemNotSellable, // TODO: capture what item was attempted to be sold + ItemNotSellable(InventoryItem), // TODO: capture what item was attempted to be sold WalletFull, } @@ -856,7 +856,8 @@ impl ItemManager { let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?; let sold_item_handle = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?; if let Some(item_sold) = sold_item_handle.item() { - if let Some(unit_price) = item_sold.get_sell_price() { // -> Option u32 = meseta, or None if error + // if let Some(unit_price) = item_sold.get_sell_price() { // -> Option u32 = meseta, or None if error + let unit_price = item_sold.get_sell_price()?; { // -> Result // ItemMangerError::InvalidSale let total_sale = unit_price * amount as u32; if character.meseta + total_sale <= 999999 { character.meseta += total_sale; @@ -880,8 +881,6 @@ impl ItemManager { } else { return Err(ItemManagerError::WalletFull.into()); } - } else { - return Err(ItemManagerError::ItemNotSellable.into()); } } else { return Err(ItemManagerError::ItemIdNotInInventory(item_id).into()) diff --git a/src/ship/shops/armor.rs b/src/ship/shops/armor.rs index 282cf96..83afca2 100644 --- a/src/ship/shops/armor.rs +++ b/src/ship/shops/armor.rs @@ -14,7 +14,7 @@ use crate::ship::item_stats::{ARMOR_STATS, SHIELD_STATS, UNIT_STATS}; #[derive(Debug)] pub enum ArmorShopItem { - Frame(ArmorType, usize), + Frame(ArmorType, usize), // slots Barrier(ShieldType), Unit(UnitType), } @@ -90,17 +90,35 @@ impl ShopItem for ArmorShopItem { } } -impl ArmorShopItem { - pub fn armor_from_item(a: &Armor) -> ArmorShopItem { - ArmorShopItem::Frame(a.armor, a.slots as usize) +// impl ArmorShopItem { +// pub fn armor_from_item(a: &Armor) -> ArmorShopItem { +// ArmorShopItem::Frame(a.armor, a.slots as usize) +// } + +// pub fn shield_from_item(s: &Shield) -> ArmorShopItem { +// ArmorShopItem::Barrier(s.shield) +// } + +// pub fn unit_from_item(u: &Unit) -> ArmorShopItem { +// ArmorShopItem::Unit(u.unit) +// } +// } + +impl From<&Armor> for ArmorShopItem { + fn from(armor: &Armor) -> ArmorShopItem { + ArmorShopItem::Frame(armor.armor, armor.slots as usize) } +} - pub fn shield_from_item(s: &Shield) -> ArmorShopItem { - ArmorShopItem::Barrier(s.shield) +impl From<&Shield> for ArmorShopItem { + fn from(shield: &Shield) -> ArmorShopItem { + ArmorShopItem::Barrier(shield.shield) } +} - pub fn unit_from_item(u: &Unit) -> ArmorShopItem { - ArmorShopItem::Unit(u.unit) +impl From<&Unit> for ArmorShopItem { + fn from(unit: &Unit) -> ArmorShopItem { + ArmorShopItem::Unit(unit.unit) } } diff --git a/src/ship/shops/tool.rs b/src/ship/shops/tool.rs index e68f38d..2a025c6 100644 --- a/src/ship/shops/tool.rs +++ b/src/ship/shops/tool.rs @@ -96,13 +96,25 @@ impl ShopItem for ToolShopItem { } } -impl ToolShopItem { - pub fn tool_from_item(t: &Tool) -> ToolShopItem { - ToolShopItem::Tool(t.tool) +// impl ToolShopItem { +// pub fn tool_from_item(t: &Tool) -> ToolShopItem { +// ToolShopItem::Tool(t.tool) +// } + +// pub fn tech_from_item(d: &TechniqueDisk) -> ToolShopItem { +// ToolShopItem::Tech(*d) +// } +// } + +impl From<&Tool> for ToolShopItem { + fn from(tool: &Tool) -> ToolShopItem { + ToolShopItem::Tool(tool.tool) } +} - pub fn tech_from_item(d: &TechniqueDisk) -> ToolShopItem { - ToolShopItem::Tech(*d) +impl From<&TechniqueDisk> for ToolShopItem { + fn from(techdisk: &TechniqueDisk) -> ToolShopItem { + ToolShopItem::Tech(*techdisk) } } diff --git a/src/ship/shops/weapon.rs b/src/ship/shops/weapon.rs index 7bdae25..1f53cf7 100644 --- a/src/ship/shops/weapon.rs +++ b/src/ship/shops/weapon.rs @@ -53,6 +53,17 @@ impl PartialOrd for WeaponShopItem { } } +impl From<&Weapon> for WeaponShopItem { + fn from(weapon: &Weapon) -> WeaponShopItem { + WeaponShopItem { + weapon: weapon.weapon, + special: weapon.special, + grind: weapon.grind as usize, + attributes: weapon.attrs, + } + } +} + fn special_stars(special: &WeaponSpecial) -> usize { match special { -- 2.36.0 From 66d882d336e8c273d12f689627d2dcb1c16ff599 Mon Sep 17 00:00:00 2001 From: andy Date: Sat, 31 Jul 2021 02:07:41 +0000 Subject: [PATCH 15/34] cleanup todos --- src/ship/items/inventory.rs | 21 ++------------------- src/ship/items/manager.rs | 10 ++++------ 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/ship/items/inventory.rs b/src/ship/items/inventory.rs index 405db34..df15266 100644 --- a/src/ship/items/inventory.rs +++ b/src/ship/items/inventory.rs @@ -222,7 +222,6 @@ impl InventoryItem { } } - // pub fn get_sell_price(&self) -> Option { pub fn get_sell_price(&self) -> Result { match self { InventoryItem::Individual(individual_item) => { @@ -230,66 +229,50 @@ impl InventoryItem { // TODO: can wrapped items be sold? ItemDetail::Weapon(w) => { if !w.tekked { - // return Some(1u32) return Ok(1u32) } if w.is_rare_item() { - // return Some(10u32) return Ok(10u32) } - // other item factors? - // Some((WeaponShopItem::from(w).price() / 8) as u32) Ok((WeaponShopItem::from(w).price() / 8) as u32) }, ItemDetail::Armor(a) => { if a.is_rare_item() { - // return Some(10u32) return Ok(10u32) } - // Some((ArmorShopItem::from(a).price() / 8) as u32) return Ok((ArmorShopItem::from(a).price() / 8) as u32) }, ItemDetail::Shield(s) => { if s.is_rare_item() { - // return Some(10u32) return Ok(10u32) } - // Some((ArmorShopItem::from(s).price() / 8) as u32) return Ok((ArmorShopItem::from(s).price() / 8) as u32) }, ItemDetail::Unit(u) => { if u.is_rare_item() { - // return Some(10u32) return Ok(10u32) } - // Some((ArmorShopItem::from(u).price() / 8) as u32) return Ok((ArmorShopItem::from(u).price() / 8) as u32) }, ItemDetail::Tool(t) => { if !matches!(t.tool, ToolType::PhotonDrop | ToolType::PhotonSphere | ToolType::PhotonCrystal) && t.is_rare_item() { - // return Some(10u32) return Ok(10u32) } - // Some((ToolShopItem::from(t).price() / 8) as u32) return Ok((ToolShopItem::from(t).price() / 8) as u32) }, - ItemDetail::TechniqueDisk(d) => { // TODO: are all techs the same? - // Some((ToolShopItem::from(d).price() / 8) as u32) + ItemDetail::TechniqueDisk(d) => { return Ok((ToolShopItem::from(d).price() / 8) as u32) }, - ItemDetail::Mag(_m) => { //TODO: error. mags are not sellable - // None + ItemDetail::Mag(_m) => { return Err(ItemManagerError::ItemNotSellable(self.clone())) }, ItemDetail::ESWeapon(_e) => { - // Some(10u32) // TODO: check price return Ok(10u32) }, } }, // the number of stacked items sold is handled by the caller. this is just the price of 1 InventoryItem::Stacked(stacked_item) => { - // Some((ToolShopItem::from(&stacked_item.tool).price() / 8) as u32) return Ok((ToolShopItem::from(&stacked_item.tool).price() / 8) as u32) }, } diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index 9ca85e6..f22c3a5 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -56,8 +56,9 @@ pub enum ItemManagerError { NoArmorEquipped, GatewayError(#[from] crate::entity::gateway::GatewayError), StackedItemError(Vec), - ItemNotSellable(InventoryItem), // TODO: capture what item was attempted to be sold + ItemNotSellable(InventoryItem), WalletFull, + InvalidSale, } pub struct ItemManager { @@ -856,8 +857,7 @@ impl ItemManager { let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?; let sold_item_handle = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?; if let Some(item_sold) = sold_item_handle.item() { - // if let Some(unit_price) = item_sold.get_sell_price() { // -> Option u32 = meseta, or None if error - let unit_price = item_sold.get_sell_price()?; { // -> Result // ItemMangerError::InvalidSale + let unit_price = item_sold.get_sell_price()?; { let total_sale = unit_price * amount as u32; if character.meseta + total_sale <= 999999 { character.meseta += total_sale; @@ -871,8 +871,7 @@ impl ItemManager { Ordering::Less | Ordering::Equal => { sold_item_handle.consume(amount)?; }, - // TODO: put a real error here - Ordering::Greater => {println!("i can't believe you've done this.");}, + Ordering::Greater => return Err(ItemManagerError::InvalidSale.into()), }; }, } @@ -885,7 +884,6 @@ impl ItemManager { } else { return Err(ItemManagerError::ItemIdNotInInventory(item_id).into()) } - // TODO: why did i put this Ok(()) } -- 2.36.0 From b60463eaa091d468dd490cadb9130b75f80ceaa3 Mon Sep 17 00:00:00 2001 From: andy Date: Sat, 31 Jul 2021 02:21:15 +0000 Subject: [PATCH 16/34] appease the clip --- src/ship/items/inventory.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ship/items/inventory.rs b/src/ship/items/inventory.rs index df15266..7369c40 100644 --- a/src/ship/items/inventory.rs +++ b/src/ship/items/inventory.rs @@ -240,40 +240,40 @@ impl InventoryItem { if a.is_rare_item() { return Ok(10u32) } - return Ok((ArmorShopItem::from(a).price() / 8) as u32) + Ok((ArmorShopItem::from(a).price() / 8) as u32) }, ItemDetail::Shield(s) => { if s.is_rare_item() { return Ok(10u32) } - return Ok((ArmorShopItem::from(s).price() / 8) as u32) + Ok((ArmorShopItem::from(s).price() / 8) as u32) }, ItemDetail::Unit(u) => { if u.is_rare_item() { return Ok(10u32) } - return Ok((ArmorShopItem::from(u).price() / 8) as u32) + Ok((ArmorShopItem::from(u).price() / 8) as u32) }, ItemDetail::Tool(t) => { if !matches!(t.tool, ToolType::PhotonDrop | ToolType::PhotonSphere | ToolType::PhotonCrystal) && t.is_rare_item() { return Ok(10u32) } - return Ok((ToolShopItem::from(t).price() / 8) as u32) + Ok((ToolShopItem::from(t).price() / 8) as u32) }, ItemDetail::TechniqueDisk(d) => { - return Ok((ToolShopItem::from(d).price() / 8) as u32) + Ok((ToolShopItem::from(d).price() / 8) as u32) }, ItemDetail::Mag(_m) => { - return Err(ItemManagerError::ItemNotSellable(self.clone())) + Err(ItemManagerError::ItemNotSellable(self.clone())) }, ItemDetail::ESWeapon(_e) => { - return Ok(10u32) + Ok(10u32) }, } }, // the number of stacked items sold is handled by the caller. this is just the price of 1 InventoryItem::Stacked(stacked_item) => { - return Ok((ToolShopItem::from(&stacked_item.tool).price() / 8) as u32) + Ok((ToolShopItem::from(&stacked_item.tool).price() / 8) as u32) }, } } -- 2.36.0 From 58d5d1ed746955ae9fbb46b209b1855afb20c047 Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 30 Jul 2021 22:06:05 -0600 Subject: [PATCH 17/34] update bcrypt --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 368c23a..33acf8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ futures = "0.3.5" rand = "0.7.3" rand_chacha = "0.2.2" crc = "^1.0.0" -bcrypt = "0.4" +bcrypt = "0.10" chrono = "0.4.11" serde = "*" serde_json = "*" -- 2.36.0 From 8acbb914169a91b3bd1a869fe529785ddc373d36 Mon Sep 17 00:00:00 2001 From: andy Date: Sat, 31 Jul 2021 04:36:12 +0000 Subject: [PATCH 18/34] don't need these anymore --- src/ship/shops/armor.rs | 14 -------------- src/ship/shops/tool.rs | 10 ---------- 2 files changed, 24 deletions(-) diff --git a/src/ship/shops/armor.rs b/src/ship/shops/armor.rs index 83afca2..23baa46 100644 --- a/src/ship/shops/armor.rs +++ b/src/ship/shops/armor.rs @@ -90,20 +90,6 @@ impl ShopItem for ArmorShopItem { } } -// impl ArmorShopItem { -// pub fn armor_from_item(a: &Armor) -> ArmorShopItem { -// ArmorShopItem::Frame(a.armor, a.slots as usize) -// } - -// pub fn shield_from_item(s: &Shield) -> ArmorShopItem { -// ArmorShopItem::Barrier(s.shield) -// } - -// pub fn unit_from_item(u: &Unit) -> ArmorShopItem { -// ArmorShopItem::Unit(u.unit) -// } -// } - impl From<&Armor> for ArmorShopItem { fn from(armor: &Armor) -> ArmorShopItem { ArmorShopItem::Frame(armor.armor, armor.slots as usize) diff --git a/src/ship/shops/tool.rs b/src/ship/shops/tool.rs index 2a025c6..b5f9718 100644 --- a/src/ship/shops/tool.rs +++ b/src/ship/shops/tool.rs @@ -96,16 +96,6 @@ impl ShopItem for ToolShopItem { } } -// impl ToolShopItem { -// pub fn tool_from_item(t: &Tool) -> ToolShopItem { -// ToolShopItem::Tool(t.tool) -// } - -// pub fn tech_from_item(d: &TechniqueDisk) -> ToolShopItem { -// ToolShopItem::Tech(*d) -// } -// } - impl From<&Tool> for ToolShopItem { fn from(tool: &Tool) -> ToolShopItem { ToolShopItem::Tool(tool.tool) -- 2.36.0 From d48494d5b37d312c160b7b432e68ba3a3d44f606 Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 4 Aug 2021 02:26:00 +0000 Subject: [PATCH 19/34] update inventory for ingame selling tests --- src/bin/main.rs | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index ee9aa8c..05fc80d 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -241,22 +241,13 @@ fn main() { }).await.unwrap(); entity_gateway.use_mag_cell(&item5_m.id, &cell.id).await.unwrap(); - entity_gateway.create_item( + let item6_1 = entity_gateway.create_item( NewItemEntity { - item: ItemDetail::Weapon( - item::weapon::Weapon { - weapon: item::weapon::WeaponType::Autogun, - grind: 5, - special: Some(item::weapon::WeaponSpecial::Hell), - attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 70}), - Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 80}), - None,], - tekked: false, - } + item: ItemDetail::ESWeapon( + item::esweapon::ESWeapon::new(item::esweapon::ESWeaponType::Saber) ), - location: ItemLocation::Bank { + location: ItemLocation::Inventory { character_id: character.id, - name: item::BankName("".to_string()), } }).await.unwrap(); let item7_a = entity_gateway.create_item( @@ -264,8 +255,8 @@ fn main() { item: ItemDetail::Armor( item::armor::Armor { armor: item::armor::ArmorType::Frame, - dfp: 0, - evp: 0, + dfp: 2, + evp: 2, slots: 4, } ), @@ -279,8 +270,8 @@ fn main() { item: ItemDetail::Shield( item::shield::Shield { shield: item::shield::ShieldType::Barrier, - dfp: 0, - evp: 0, + dfp: 5, + evp: 5, } ), location: ItemLocation::Inventory { @@ -293,7 +284,7 @@ fn main() { item: ItemDetail::Unit( item::unit::Unit { unit: item::unit::UnitType::PriestMind, - modifier: Some(item::unit::UnitModifier::Minus), + modifier: Some(item::unit::UnitModifier::PlusPlus), } ), location: ItemLocation::Inventory { @@ -306,7 +297,7 @@ fn main() { item: ItemDetail::Unit( item::unit::Unit { unit: item::unit::UnitType::PriestMind, - modifier: Some(item::unit::UnitModifier::Minus), + modifier: Some(item::unit::UnitModifier::Plus), } ), location: ItemLocation::Inventory { @@ -332,7 +323,7 @@ fn main() { item: ItemDetail::Unit( item::unit::Unit { unit: item::unit::UnitType::PriestMind, - modifier: Some(item::unit::UnitModifier::Minus), + modifier: Some(item::unit::UnitModifier::MinusMinus), } ), location: ItemLocation::Inventory { @@ -377,7 +368,7 @@ fn main() { }; entity_gateway.set_character_equips(&character.id, &equipped).await.unwrap(); - let inventory = item::InventoryEntity::new(vec![item0, item1, item2_w, item3, item4, item5_m, item6, item7_a, item8_s, item9_u0, item10_u1, item11_u2, item12_u3, item13, item14]); + let inventory = item::InventoryEntity::new(vec![item0, item1, item2_w, item3, item4, item5_m, item6, item6_1, item7_a, item8_s, item9_u0, item10_u1, item11_u2, item12_u3, item13, item14]); entity_gateway.set_character_inventory(&character.id, &inventory).await.unwrap(); entity_gateway.set_character_bank(&character.id, &item::BankEntity::default(), item::BankName("".into())).await.unwrap(); } -- 2.36.0 From ab404d0cae2e157e48135398f2b064d525e32e12 Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 4 Aug 2021 02:27:41 +0000 Subject: [PATCH 20/34] unit modifier to star value changes --- src/entity/item/unit.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/entity/item/unit.rs b/src/entity/item/unit.rs index cc973ed..371f450 100644 --- a/src/entity/item/unit.rs +++ b/src/entity/item/unit.rs @@ -446,4 +446,14 @@ impl Unit { | UnitType::PbIncrease ) } + + pub fn modifier_stars(&self) -> i8 { + match self.modifier { + Some(UnitModifier::PlusPlus) => 1, + Some(UnitModifier::Plus) => 1, + Some(UnitModifier::Minus) => -1, + Some(UnitModifier::MinusMinus) => -1, + _ => 0, + } + } } -- 2.36.0 From e18eebb5e9f0babc14d8caefd29414d7e3c05618 Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 4 Aug 2021 02:28:29 +0000 Subject: [PATCH 21/34] change armor shop item structs to handle non-0 dfp/evp for selling --- src/ship/shops/armor.rs | 68 ++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/src/ship/shops/armor.rs b/src/ship/shops/armor.rs index 23baa46..b85fe12 100644 --- a/src/ship/shops/armor.rs +++ b/src/ship/shops/armor.rs @@ -12,47 +12,55 @@ use crate::entity::item::unit::{Unit, UnitType}; use crate::ship::shops::ShopItem; use crate::ship::item_stats::{ARMOR_STATS, SHIELD_STATS, UNIT_STATS}; +// #[derive(Debug)] +// pub enum ArmorShopItem { +// Frame(ArmorType, usize), // slots +// Barrier(ShieldType), +// Unit(UnitType), +// } + #[derive(Debug)] pub enum ArmorShopItem { - Frame(ArmorType, usize), // slots - Barrier(ShieldType), - Unit(UnitType), + Frame(Armor), // slots + Barrier(Shield), + Unit(Unit), } const ARMOR_MULTIPLIER: f32 = 0.799_999_95; const SHIELD_MULTIPLIER: f32 = 1.5; const UNIT_MULTIPLIER: f32 = 1000.0; +// TODO: reduce the number of type casts? impl ShopItem for ArmorShopItem { fn price(&self) -> usize { match self { - ArmorShopItem::Frame(frame, slot) => { - ARMOR_STATS.get(frame) + ArmorShopItem::Frame(frame) => { + ARMOR_STATS.get(&frame.armor) .map(|frame_stats| { - let mut price = (frame_stats.dfp + frame_stats.evp) as f32; + let mut price = (frame_stats.dfp + frame_stats.evp + frame.dfp as i32 + frame.evp as i32) as f32; price *= price; price /= ARMOR_MULTIPLIER; - price += 70.0 * frame_stats.level_req as f32; - price += 70.0 * frame_stats.level_req as f32 * *slot as f32; + price += 70.0 * (frame_stats.level_req + 1) as f32; + price += 70.0 * (frame_stats.level_req + 1) as f32 * frame.slots as f32; price as usize }) .unwrap_or(0xFFFF) }, ArmorShopItem::Barrier(barrier) => { - SHIELD_STATS.get(barrier) + SHIELD_STATS.get(&barrier.shield) .map(|barrier_stats| { - let mut price = (barrier_stats.dfp + barrier_stats.evp) as f32; + let mut price = (barrier_stats.dfp + barrier_stats.evp + barrier.dfp as i32 + barrier.evp as i32) as f32; price *= price; price /= SHIELD_MULTIPLIER; - price += 70.0 * barrier_stats.level_req as f32; + price += 70.0 * (barrier_stats.level_req + 1) as f32; price as usize }) .unwrap_or(0xFFFF) }, ArmorShopItem::Unit(unit) => { - UNIT_STATS.get(unit) + UNIT_STATS.get(&unit.unit) .map(|unit_stats| { - (unit_stats.stars as f32 * UNIT_MULTIPLIER) as usize + ((unit_stats.stars as f32 + unit.modifier_stars() as f32) * UNIT_MULTIPLIER) as usize }) .unwrap_or(0xFFFF) } @@ -65,24 +73,24 @@ impl ShopItem for ArmorShopItem { fn as_item(&self) -> ItemDetail { match self { - ArmorShopItem::Frame(frame, slot) => { + ArmorShopItem::Frame(frame) => { ItemDetail::Armor(Armor { - armor: *frame, + armor: frame.armor, dfp: 0, evp: 0, - slots: *slot as u8, + slots: frame.slots as u8, }) }, ArmorShopItem::Barrier(barrier) => { ItemDetail::Shield(Shield { - shield: *barrier, + shield: barrier.shield, dfp: 0, evp: 0, }) }, ArmorShopItem::Unit(unit) => { ItemDetail::Unit(Unit { - unit: *unit, + unit: unit.unit, modifier: None, }) }, @@ -92,19 +100,19 @@ impl ShopItem for ArmorShopItem { impl From<&Armor> for ArmorShopItem { fn from(armor: &Armor) -> ArmorShopItem { - ArmorShopItem::Frame(armor.armor, armor.slots as usize) + ArmorShopItem::Frame(*armor) } } impl From<&Shield> for ArmorShopItem { fn from(shield: &Shield) -> ArmorShopItem { - ArmorShopItem::Barrier(shield.shield) + ArmorShopItem::Barrier(*shield) } } impl From<&Unit> for ArmorShopItem { fn from(unit: &Unit) -> ArmorShopItem { - ArmorShopItem::Unit(unit.unit) + ArmorShopItem::Unit(*unit) } } @@ -280,7 +288,12 @@ impl ArmorShop { let frame_detail = tier.item.get(frame_choice.sample(&mut self.rng)).unwrap(); let slot = self.frame.slot_rate.get(slot_choice.sample(&mut self.rng)).unwrap(); - ArmorShopItem::Frame(frame_detail.item, slot.slot) + ArmorShopItem::Frame(Armor { + armor: frame_detail.item, + dfp: 0, + evp: 0, + slots: slot.slot as u8, + }) }) .collect() } @@ -297,7 +310,11 @@ impl ArmorShop { .map(|_| { let barrier_detail = tier.item.get(barrier_choice.sample(&mut self.rng)).unwrap(); - ArmorShopItem::Barrier(barrier_detail.item) + ArmorShopItem::Barrier(Shield { + shield: barrier_detail.item, + dfp: 0, + evp: 0, + }) }) .collect() } @@ -313,7 +330,10 @@ impl ArmorShop { .map(|_| { let unit_detail = tier.item.get(unit_choice.sample(&mut self.rng)).unwrap(); - ArmorShopItem::Unit(unit_detail.item) + ArmorShopItem::Unit(Unit { + unit: unit_detail.item, + modifier: None, + }) }) .collect() }) -- 2.36.0 From 89ddec480eecf63a05070577eeea8d92068f76f1 Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 4 Aug 2021 02:28:54 +0000 Subject: [PATCH 22/34] more selling tests! --- tests/test_shops.rs | 400 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 398 insertions(+), 2 deletions(-) diff --git a/tests/test_shops.rs b/tests/test_shops.rs index 831109c..acf295f 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -725,7 +725,7 @@ async fn test_player_sells_rare_item() { } #[async_std::test] -async fn test_player_sells_photon_drops() { +async fn test_player_sells_partial_photon_drop_stack() { let mut entity_gateway = InMemoryGateway::default(); let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; @@ -769,4 +769,400 @@ async fn test_player_sells_photon_drops() { let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert_eq!(c1.meseta, 3000); -} \ No newline at end of file +} + +#[async_std::test] +async fn test_player_sells_basic_frame() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Armor( + item::armor::Armor { + armor: item::armor::ArmorType::Frame, + dfp: 0, + evp: 0, + slots: 0, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 24); +} + +#[async_std::test] +async fn test_player_sells_max_frame() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Armor( + item::armor::Armor { + armor: item::armor::ArmorType::Frame, + dfp: 2, + evp: 2, + slots: 4, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 74); +} + +#[async_std::test] +async fn test_player_sells_basic_barrier() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Shield( + item::shield::Shield { + shield: item::shield::ShieldType::Barrier, + dfp: 0, + evp: 0, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 69); +} + +#[async_std::test] +async fn test_player_sells_max_barrier() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Shield( + item::shield::Shield { + shield: item::shield::ShieldType::Barrier, + dfp: 5, + evp: 5, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 122); +} + +#[async_std::test] +async fn test_player_sells_1_star_minusminus_unit() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Unit( + item::unit::Unit { + unit: item::unit::UnitType::PriestMind, + modifier: Some(item::unit::UnitModifier::MinusMinus), + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 125); +} + +#[async_std::test] +async fn test_player_sells_5_star_plusplus_unit() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Unit( + item::unit::Unit { + unit: item::unit::UnitType::GeneralHp, + modifier: Some(item::unit::UnitModifier::PlusPlus), + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 625); +} + +#[async_std::test] +async fn test_player_sells_rare_frame() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Armor( + item::armor::Armor { + armor: item::armor::ArmorType::StinkFrame, + dfp: 10, + evp: 20, + slots: 3, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 10); +} + +#[async_std::test] +async fn test_player_sells_rare_barrier() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Shield( + item::shield::Shield { + shield: item::shield::ShieldType::RedRing, + dfp: 10, + evp: 20, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 10); +} + +#[async_std::test] +async fn test_player_sells_rare_unit() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Unit( + item::unit::Unit { + unit: item::unit::UnitType::V101, + modifier: None, + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + } + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + + ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.unwrap().for_each(drop); + + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); + let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); + assert_eq!(c1.meseta, 10); +} -- 2.36.0 From 2dc34f9f28ee3c5f213620d57d47021aa604b249 Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 4 Aug 2021 02:58:17 +0000 Subject: [PATCH 23/34] rename test --- tests/test_shops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_shops.rs b/tests/test_shops.rs index acf295f..eb1098f 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -629,7 +629,7 @@ async fn test_units_disappear_from_shop_when_bought() { } #[async_std::test] -async fn test_selling_untekked_weapon() { +async fn test_player_sells_untekked_weapon() { let mut entity_gateway = InMemoryGateway::default(); let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; -- 2.36.0 From dacbf1eea384ecddeaa1cb21b89c908ac3730131 Mon Sep 17 00:00:00 2001 From: andy Date: Sun, 23 May 2021 18:18:36 +0000 Subject: [PATCH 24/34] add level requirements for rooms and update tests --- src/ship/packet/handler/room.rs | 68 ++++++++++++++++++++++++++++++--- src/ship/room.rs | 5 ++- src/ship/ship.rs | 2 +- tests/test_shops.rs | 6 +-- 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index c3be9dc..a058f9a 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -7,20 +7,47 @@ use crate::ship::location::{ClientLocation, RoomId, RoomLobby, ClientLocationErr use crate::ship::packet::builder; use crate::ship::room; use crate::ship::items::ItemManager; +use std::convert::{TryFrom}; pub fn create_room(id: ClientId, create_room: &CreateRoom, client_location: &mut ClientLocation, clients: &mut Clients, item_manager: &mut ItemManager, + level_table: &CharacterLevelTable, rooms: &mut Rooms) - -> Result + Send>, ShipError> { + -> Result + Send>, anyhow::Error> { + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; + let level = level_table.get_level_from_exp(client.character.char_class, client.character.exp); + match room::Difficulty::try_from(create_room.difficulty)? { + room::Difficulty::Ultimate => { + if level < 80 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto create Ultimate rooms.".into())))].into_iter())) + } + }, + room::Difficulty::VeryHard => { + if level < 40 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto create Very Hard rooms.".into())))].into_iter())) + } + }, + room::Difficulty::Hard => { + if level < 20 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto create Hard rooms.".into())))].into_iter())) + } + }, + room::Difficulty::Normal => { + if level < 1 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto create Normal rooms.".into())))].into_iter())) + } + }, + // i can't believe you've done this + _ => {unreachable!()}, + }; + let area = client_location.get_area(id).unwrap(); let area_client = client_location.get_local_client(id).unwrap(); let lobby_neighbors = client_location.get_client_neighbors(id).unwrap(); let room_id = client_location.create_new_room(id).unwrap(); - - let client = clients.get_mut(&id).unwrap();//.ok_or(ShipError::ClientNotFound(id)).unwrap(); let mut room = room::RoomState::from_create_room(create_room, client.character.section_id).unwrap(); room.bursting = true; @@ -63,11 +90,40 @@ pub fn join_room(id: ClientId, level_table: &CharacterLevelTable, rooms: &mut Rooms) -> Result + Send>, ShipError> { + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; + let level = level_table.get_level_from_exp(client.character.char_class, client.character.exp); + let room = rooms.get(pkt.item as usize) + .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?.as_ref() + .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?; + + match room.mode.difficulty() { + room::Difficulty::Ultimate => { + if level < 80 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto join Ultimate rooms.".into())))].into_iter())) + } + }, + room::Difficulty::VeryHard => { + if level < 40 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto join Very Hard rooms.".into())))].into_iter())) + } + }, + room::Difficulty::Hard => { + if level < 20 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.".into())))].into_iter())) + } + }, + room::Difficulty::Normal => { + if level < 1 { + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto join Normal rooms.".into())))].into_iter())) + } + }, + }; + let original_area = client_location.get_area(id).unwrap(); let original_neighbors = client_location.get_client_neighbors(id).unwrap(); - let room = rooms.get(pkt.item as usize) - .ok_or(ShipError::InvalidRoom(pkt.item))?.as_ref() - .ok_or(ShipError::InvalidRoom(pkt.item))?; + // let room = rooms.get(pkt.item as usize) + // .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?.as_ref() + // .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?; if room.bursting { return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("player is bursting\nplease wait".into())))].into_iter())) } diff --git a/src/ship/room.rs b/src/ship/room.rs index 3aae5da..991de54 100644 --- a/src/ship/room.rs +++ b/src/ship/room.rs @@ -7,14 +7,15 @@ use crate::ship::drops::DropTable; use crate::entity::character::SectionID; use crate::ship::monster::{load_monster_stats_table, MonsterType, MonsterStats}; use crate::ship::map::area::MapAreaLookup; +use thiserror::Error; -#[derive(Debug)] +#[derive(Debug, Error)] +#[error("")] pub enum RoomCreationError { InvalidMode, InvalidEpisode(u8), InvalidDifficulty(u8), CouldNotLoadMonsterStats(RoomMode), - } #[derive(Debug, Copy, Clone, derive_more::Display)] diff --git a/src/ship/ship.rs b/src/ship/ship.rs index ae9255d..7e79552 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -635,7 +635,7 @@ impl ServerState for ShipServerState { }, RecvShipPacket::CreateRoom(create_room) => { let block = self.blocks.with_client(id, &self.clients)?; - handler::room::create_room(id, create_room, &mut block.client_location, &mut self.clients, &mut self.item_manager, &mut block.rooms)? + handler::room::create_room(id, create_room, &mut block.client_location, &mut self.clients, &mut self.item_manager, &self.level_table, &mut block.rooms)? }, RecvShipPacket::RoomNameRequest(_req) => { let block = self.blocks.with_client(id, &self.clients)?; diff --git a/tests/test_shops.rs b/tests/test_shops.rs index eb1098f..5c414f1 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -323,7 +323,7 @@ async fn test_other_clients_see_purchase() { 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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Normal).await; join_room(&mut ship, ClientId(2), 0).await; ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::ShopRequest(ShopRequest { @@ -377,7 +377,7 @@ async fn test_other_clients_see_stacked_purchase() { 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_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Normal).await; join_room(&mut ship, ClientId(2), 0).await; ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::ShopRequest(ShopRequest { @@ -414,7 +414,7 @@ async fn test_buying_item_without_enough_mseseta() { .build()); log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Normal).await; ship.handle(ClientId(1), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::ShopRequest(ShopRequest { client: 255, -- 2.36.0 From bb5d157439a034a512e1a26312f8e0f9a58ff267 Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 22 Jun 2021 03:20:05 +0000 Subject: [PATCH 25/34] missing nuls is too advanced for the client? --- src/ship/packet/handler/room.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index a058f9a..8841d87 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -22,22 +22,22 @@ pub fn create_room(id: ClientId, match room::Difficulty::try_from(create_room.difficulty)? { room::Difficulty::Ultimate => { if level < 80 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto create Ultimate rooms.".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto create Ultimate rooms.\0".into())))].into_iter())) } }, room::Difficulty::VeryHard => { if level < 40 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto create Very Hard rooms.".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto create Very Hard rooms.\0".into())))].into_iter())) } }, room::Difficulty::Hard => { if level < 20 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto create Hard rooms.".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto create Hard rooms.\0".into())))].into_iter())) } }, room::Difficulty::Normal => { if level < 1 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto create Normal rooms.".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto create Normal rooms.\0".into())))].into_iter())) } }, // i can't believe you've done this @@ -99,22 +99,22 @@ pub fn join_room(id: ClientId, match room.mode.difficulty() { room::Difficulty::Ultimate => { if level < 80 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto join Ultimate rooms.".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto join Ultimate rooms.\0".into())))].into_iter())) } }, room::Difficulty::VeryHard => { if level < 40 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto join Very Hard rooms.".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto join Very Hard rooms.\0".into())))].into_iter())) } }, room::Difficulty::Hard => { if level < 20 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.\0".into())))].into_iter())) } }, room::Difficulty::Normal => { if level < 1 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto join Normal rooms.".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto join Normal rooms.\0".into())))].into_iter())) } }, }; -- 2.36.0 From f29b59507abc9b57b5133fcc490191f42361f50c Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 22 Jun 2021 23:23:22 +0000 Subject: [PATCH 26/34] don't expect people to remember null in Rust --- src/ship/packet/handler/room.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index 8841d87..a058f9a 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -22,22 +22,22 @@ pub fn create_room(id: ClientId, match room::Difficulty::try_from(create_room.difficulty)? { room::Difficulty::Ultimate => { if level < 80 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto create Ultimate rooms.\0".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto create Ultimate rooms.".into())))].into_iter())) } }, room::Difficulty::VeryHard => { if level < 40 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto create Very Hard rooms.\0".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto create Very Hard rooms.".into())))].into_iter())) } }, room::Difficulty::Hard => { if level < 20 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto create Hard rooms.\0".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto create Hard rooms.".into())))].into_iter())) } }, room::Difficulty::Normal => { if level < 1 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto create Normal rooms.\0".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto create Normal rooms.".into())))].into_iter())) } }, // i can't believe you've done this @@ -99,22 +99,22 @@ pub fn join_room(id: ClientId, match room.mode.difficulty() { room::Difficulty::Ultimate => { if level < 80 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto join Ultimate rooms.\0".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 80 \nto join Ultimate rooms.".into())))].into_iter())) } }, room::Difficulty::VeryHard => { if level < 40 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto join Very Hard rooms.\0".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 40 \nto join Very Hard rooms.".into())))].into_iter())) } }, room::Difficulty::Hard => { if level < 20 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.\0".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.".into())))].into_iter())) } }, room::Difficulty::Normal => { if level < 1 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto join Normal rooms.\0".into())))].into_iter())) + return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto join Normal rooms.".into())))].into_iter())) } }, }; -- 2.36.0 From cd8ebc23a0d5da52ee3218ad2ac9381bc8f0f702 Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 23 Jun 2021 00:00:46 +0000 Subject: [PATCH 27/34] imagine being level 0 --- src/ship/packet/handler/room.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index a058f9a..19a9296 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -35,11 +35,6 @@ pub fn create_room(id: ClientId, return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto create Hard rooms.".into())))].into_iter())) } }, - room::Difficulty::Normal => { - if level < 1 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto create Normal rooms.".into())))].into_iter())) - } - }, // i can't believe you've done this _ => {unreachable!()}, }; @@ -112,11 +107,6 @@ pub fn join_room(id: ClientId, return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.".into())))].into_iter())) } }, - room::Difficulty::Normal => { - if level < 1 { - return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 1 \nto join Normal rooms.".into())))].into_iter())) - } - }, }; let original_area = client_location.get_area(id).unwrap(); -- 2.36.0 From fef3b94732b8c6c4c86a6cb13134b934c6d35a67 Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 23 Jun 2021 00:02:31 +0000 Subject: [PATCH 28/34] cleanup --- src/ship/packet/handler/room.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index 19a9296..f2ff793 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -107,13 +107,11 @@ pub fn join_room(id: ClientId, return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto join Hard rooms.".into())))].into_iter())) } }, + _ => {}, }; let original_area = client_location.get_area(id).unwrap(); let original_neighbors = client_location.get_client_neighbors(id).unwrap(); - // let room = rooms.get(pkt.item as usize) - // .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?.as_ref() - // .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?; if room.bursting { return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("player is bursting\nplease wait".into())))].into_iter())) } -- 2.36.0 From 7c85199e4c33de46490325d48d50ab4ce7c00166 Mon Sep 17 00:00:00 2001 From: andy Date: Wed, 23 Jun 2021 01:03:54 +0000 Subject: [PATCH 29/34] andy vs. clippy round 3 --- src/ship/packet/handler/room.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index f2ff793..60339bb 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -35,8 +35,7 @@ pub fn create_room(id: ClientId, return Ok(Box::new(vec![(id, SendShipPacket::SmallDialog(SmallDialog::new("You must be at least level 20 \nto create Hard rooms.".into())))].into_iter())) } }, - // i can't believe you've done this - _ => {unreachable!()}, + room::Difficulty::Normal => {}, }; let area = client_location.get_area(id).unwrap(); @@ -87,9 +86,7 @@ pub fn join_room(id: ClientId, -> Result + Send>, ShipError> { let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; let level = level_table.get_level_from_exp(client.character.char_class, client.character.exp); - let room = rooms.get(pkt.item as usize) - .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?.as_ref() - .ok_or_else(|| ShipError::InvalidRoom(pkt.item))?; + let room = rooms.get(pkt.item as usize).ok_or(ShipError::InvalidRoom(pkt.item))?.as_ref().unwrap(); // clippy look what you made me do match room.mode.difficulty() { room::Difficulty::Ultimate => { -- 2.36.0 From 27a6c9a1367747d4099f248cea18339effdc9274 Mon Sep 17 00:00:00 2001 From: andy Date: Tue, 28 Dec 2021 01:22:46 +0000 Subject: [PATCH 30/34] creating rooms with difficulties is bad for selling tests? --- src/ship/packet/handler/direct_message.rs | 1 - tests/test_shops.rs | 26 +++++++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs index f17f1a1..2268bb7 100644 --- a/src/ship/packet/handler/direct_message.rs +++ b/src/ship/packet/handler/direct_message.rs @@ -370,7 +370,6 @@ where } }; - // TODO: stop giving away wares for free if client.character.meseta < (item.price() * buy_item.amount as usize) as u32 { return Err(ShipError::ShopError.into()) } diff --git a/tests/test_shops.rs b/tests/test_shops.rs index 5c414f1..3555c8c 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -292,7 +292,7 @@ async fn test_player_sells_3_attr_weapon_to_shop() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -662,7 +662,7 @@ async fn test_player_sells_untekked_weapon() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -710,7 +710,7 @@ async fn test_player_sells_rare_item() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -757,7 +757,7 @@ async fn test_player_sells_partial_photon_drop_stack() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -802,7 +802,7 @@ async fn test_player_sells_basic_frame() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -847,7 +847,7 @@ async fn test_player_sells_max_frame() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -891,7 +891,7 @@ async fn test_player_sells_basic_barrier() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -935,7 +935,7 @@ async fn test_player_sells_max_barrier() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -978,7 +978,7 @@ async fn test_player_sells_1_star_minusminus_unit() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -1021,7 +1021,7 @@ async fn test_player_sells_5_star_plusplus_unit() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -1066,7 +1066,7 @@ async fn test_player_sells_rare_frame() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -1110,7 +1110,7 @@ async fn test_player_sells_rare_barrier() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, @@ -1153,7 +1153,7 @@ async fn test_player_sells_rare_unit() { log_in_char(&mut ship, ClientId(1), "a1", "a").await; join_lobby(&mut ship, ClientId(1)).await; - create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await; + create_room(&mut ship, ClientId(1), "room", "").await; ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { client: 0, -- 2.36.0 From 8b776a59064cfb24eb8947b39596a1a177819ea2 Mon Sep 17 00:00:00 2001 From: jake Date: Wed, 29 Dec 2021 15:22:03 -0700 Subject: [PATCH 31/34] ok turns out walletfull is a real thing --- src/ship/items/manager.rs | 40 +++++++++++++++++++++---------------- src/ship/items/mod.rs | 2 +- tests/test_shops.rs | 42 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 18 deletions(-) diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index 78b2749..ac8420d 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -900,29 +900,35 @@ impl ItemManager { item_id: ClientItemId, amount: usize) -> Result<(), anyhow::Error> { + let character_meseta = self.get_character_meseta(&character.id)?.0; let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?; let sold_item_handle = inventory.get_item_handle_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?; if let Some(item_sold) = sold_item_handle.item() { let unit_price = item_sold.get_sell_price()?; { let total_sale = unit_price * amount as u32; - match item_sold { - InventoryItem::Individual(i) => { - entity_gateway.add_item_note(&i.entity_id, ItemNote::SoldToShop).await?; - inventory.remove_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?; - }, - InventoryItem::Stacked(s) => { - match amount.cmp(&s.count()) { - Ordering::Less | Ordering::Equal => { - sold_item_handle.consume(amount)?; - }, - Ordering::Greater => return Err(ItemManagerError::InvalidSale.into()), - }; - }, + if character_meseta + total_sale <= 999999 { + match item_sold { + InventoryItem::Individual(i) => { + entity_gateway.add_item_note(&i.entity_id, ItemNote::SoldToShop).await?; + inventory.remove_by_id(item_id).ok_or(ItemManagerError::NoSuchItemId(item_id))?; + }, + InventoryItem::Stacked(s) => { + match amount.cmp(&s.count()) { + Ordering::Less | Ordering::Equal => { + sold_item_handle.consume(amount)?; + }, + Ordering::Greater => return Err(ItemManagerError::InvalidSale.into()), + }; + }, + } + entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?; + let character_meseta = self.get_character_meseta_mut(&character.id)?; + character_meseta.0 += total_sale; + entity_gateway.set_character_meseta(&character.id, *character_meseta).await?; + } + else { + return Err(ItemManagerError::WalletFull.into()) } - entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?; - let character_meseta = self.get_character_meseta_mut(&character.id)?; - character_meseta.0 += total_sale; - entity_gateway.set_character_meseta(&character.id, *character_meseta).await?; } } else { return Err(ItemManagerError::ItemIdNotInInventory(item_id).into()) diff --git a/src/ship/items/mod.rs b/src/ship/items/mod.rs index 0d76eb3..8a917a8 100644 --- a/src/ship/items/mod.rs +++ b/src/ship/items/mod.rs @@ -1,7 +1,7 @@ mod bank; mod floor; pub mod inventory; -mod manager; +pub mod manager; pub mod transaction; pub mod use_tool; use serde::{Serialize, Deserialize}; diff --git a/tests/test_shops.rs b/tests/test_shops.rs index 987f43c..27d7f06 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -3,6 +3,7 @@ use elseware::entity::gateway::{EntityGateway, InMemoryGateway}; use elseware::entity::item; use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket}; use elseware::ship::room::Difficulty; +use elseware::ship::items::manager::ItemManagerError; use libpso::packet::ship::*; use libpso::packet::messages::*; @@ -1105,3 +1106,44 @@ async fn test_player_sells_rare_unit() { let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap(); assert_eq!(c1_meseta.0, 10); } + +#[async_std::test] +async fn test_player_cant_sell_if_meseta_would_go_over_max() { + let mut entity_gateway = InMemoryGateway::default(); + + let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + entity_gateway.set_character_meseta(&char1.id, item::Meseta(999995)).await.unwrap(); + + let mut p1_inv = Vec::new(); + + p1_inv.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Unit( + item::unit::Unit { + unit: item::unit::UnitType::V101, + modifier: None, + } + ), + }).await.unwrap()); + + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_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; + + let ack = ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerSoldItem(PlayerSoldItem { + client: 0, + target: 0, + item_id: 0x10000, + amount: 1, + })))).await.err().unwrap(); + assert!(matches!(ack.downcast::().unwrap(), ItemManagerError::WalletFull)); + + let c1_meseta = entity_gateway.get_character_meseta(&char1.id).await.unwrap(); + assert_eq!(c1_meseta.0, 999995); +} -- 2.36.0 From ed8bcbc812623d673f8bdad6ba0b351d1c90a8e3 Mon Sep 17 00:00:00 2001 From: jake Date: Wed, 29 Dec 2021 15:22:28 -0700 Subject: [PATCH 32/34] everything into the inventory --- src/bin/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 931af87..91f0815 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -325,7 +325,7 @@ fn main() { }; entity_gateway.set_character_equips(&character.id, &equipped).await.unwrap(); - let inventory = item::InventoryEntity::new(vec![InventoryItemEntity::from(item0), item1.into(), item2_w.into(), item3.into(), item4.into(), item5_m.into(), item6.into(), item7_a.into(), item8_s.into(), item9_u0.into(), item10_u1.into(), item11_u2.into(), item12_u3.into(), item13.into(), item14.into(), monomates.into()]); + let inventory = item::InventoryEntity::new(vec![InventoryItemEntity::from(item0), item1.into(), item2_w.into(), item3.into(), item4.into(), item5_m.into(), item6.into(), item6_1.into(), item7_a.into(), item8_s.into(), item9_u0.into(), item10_u1.into(), item11_u2.into(), item12_u3.into(), item13.into(), item14.into(), monomates.into()]); entity_gateway.set_character_inventory(&character.id, &inventory).await.unwrap(); entity_gateway.set_character_bank(&character.id, &item::BankEntity::default(), item::BankName("".into())).await.unwrap(); } -- 2.36.0 From ea4c085dfd7e97a6867f145e8c41938a02d6a06b Mon Sep 17 00:00:00 2001 From: jake Date: Wed, 29 Dec 2021 15:46:22 -0700 Subject: [PATCH 33/34] satiate the clip's hunger for properness --- src/entity/gateway/postgres/postgres.rs | 8 ++++---- src/entity/item/mod.rs | 1 + src/entity/item/weapon.rs | 3 +++ src/ship/character.rs | 15 +++++++++++++++ src/ship/items/manager.rs | 6 +++--- src/ship/map/area.rs | 1 + src/ship/map/maps.rs | 4 ++-- src/ship/packet/handler/direct_message.rs | 15 +++++++-------- src/ship/packet/handler/message.rs | 19 +++++++++---------- src/ship/packet/handler/quest.rs | 8 ++++---- src/ship/packet/handler/room.rs | 4 ++-- src/ship/packet/handler/trade.rs | 8 +++----- src/ship/ship.rs | 6 ++++++ src/ship/trade.rs | 2 +- 14 files changed, 61 insertions(+), 39 deletions(-) diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index 2fefb03..bbf116a 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -147,13 +147,13 @@ impl EntityGateway for PostgresGateway { let new_settings = sqlx::query_as::<_, PgUserSettings>("insert into user_settings (user_account, blocked_users, key_config, joystick_config, option_flags, shortcuts, symbol_chats, team_name) values ($1, $2, $3, $4, $5, $6, $7, $8) returning *;") .bind(settings.user_id.0) - .bind(settings.settings.blocked_users.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::>()) + .bind(settings.settings.blocked_users.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::>()) .bind(settings.settings.key_config.to_vec()) .bind(settings.settings.joystick_config.to_vec()) .bind(settings.settings.option_flags as i32) .bind(settings.settings.shortcuts.to_vec()) .bind(settings.settings.symbol_chats.to_vec()) - .bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::>()) + .bind(settings.settings.team_name.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::>()) .fetch_one(&self.pool).await?; Ok(new_settings.into()) } @@ -167,13 +167,13 @@ impl EntityGateway for PostgresGateway { async fn save_user_settings(&mut self, settings: &UserSettingsEntity) -> Result<(), GatewayError> { sqlx::query("update user_settings set blocked_users=$1, key_config=$2, joystick_config=$3, option_flags=$4, shortcuts=$5, symbol_chats=$6, team_name=$7 where id=$8") - .bind(settings.settings.blocked_users.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::>()) + .bind(settings.settings.blocked_users.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::>()) .bind(&settings.settings.key_config.to_vec()) .bind(&settings.settings.joystick_config.to_vec()) .bind(&settings.settings.option_flags) .bind(&settings.settings.shortcuts.to_vec()) .bind(&settings.settings.symbol_chats.to_vec()) - .bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::>()) + .bind(settings.settings.team_name.iter().copied().flat_map(|i| i.to_le_bytes().to_vec()).collect::>()) .bind(&settings.id.0) .fetch_one(&self.pool).await?; Ok(()) diff --git a/src/entity/item/mod.rs b/src/entity/item/mod.rs index c083d7e..c840034 100644 --- a/src/entity/item/mod.rs +++ b/src/entity/item/mod.rs @@ -202,6 +202,7 @@ impl std::convert::From> for InventoryItemEntity { } impl InventoryItemEntity { + #[must_use] pub fn map_individual ItemEntity>(self, func: F) -> InventoryItemEntity { match self { InventoryItemEntity::Individual(item) => InventoryItemEntity::Individual(func(item)), diff --git a/src/entity/item/weapon.rs b/src/entity/item/weapon.rs index 9f4ea27..5527f61 100644 --- a/src/entity/item/weapon.rs +++ b/src/entity/item/weapon.rs @@ -93,6 +93,8 @@ impl WeaponSpecial { pub fn value(&self) -> u8 { *self as u8 } + + #[must_use] pub fn rank_up(&self) -> WeaponSpecial { match self { WeaponSpecial::Draw => WeaponSpecial::Drain, @@ -138,6 +140,7 @@ impl WeaponSpecial { } } + #[must_use] pub fn rank_down(&self) -> WeaponSpecial { match self { WeaponSpecial::Draw => WeaponSpecial::Draw, diff --git a/src/ship/character.rs b/src/ship/character.rs index b1235b1..e5d4429 100644 --- a/src/ship/character.rs +++ b/src/ship/character.rs @@ -14,6 +14,7 @@ pub struct CharacterBytesBuilder<'a> { } impl<'a> CharacterBytesBuilder<'a> { + #[must_use] pub fn character(self, character: &'a CharacterEntity) -> CharacterBytesBuilder<'a> { CharacterBytesBuilder { character: Some(character), @@ -21,6 +22,7 @@ impl<'a> CharacterBytesBuilder<'a> { } } + #[must_use] pub fn stats(self, stats: &'a CharacterStats) -> CharacterBytesBuilder<'a> { CharacterBytesBuilder { stats: Some(stats), @@ -28,6 +30,7 @@ impl<'a> CharacterBytesBuilder<'a> { } } + #[must_use] pub fn level(self, level: u32) -> CharacterBytesBuilder<'a> { CharacterBytesBuilder { level: Some(level), @@ -35,6 +38,7 @@ impl<'a> CharacterBytesBuilder<'a> { } } + #[must_use] pub fn meseta(self, meseta: Meseta) -> CharacterBytesBuilder<'a> { CharacterBytesBuilder { meseta: Some(meseta), @@ -95,6 +99,7 @@ pub struct FullCharacterBytesBuilder<'a> { } impl<'a> FullCharacterBytesBuilder<'a> { + #[must_use] pub fn character(self, character: &'a CharacterEntity) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { character: Some(character), @@ -102,6 +107,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + #[must_use] pub fn stats(self, stats: &'a CharacterStats) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { stats: Some(stats), @@ -109,6 +115,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + #[must_use] pub fn level(self, level: u32) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { level: Some(level), @@ -116,6 +123,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + #[must_use] pub fn meseta(self, meseta: Meseta) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { meseta: Some(meseta), @@ -123,6 +131,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + #[must_use] pub fn inventory(self, inventory: &'a CharacterInventory) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { inventory: Some(inventory), @@ -130,6 +139,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + #[must_use] pub fn bank(self, bank: &'a CharacterBank) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { bank: Some(bank), @@ -137,6 +147,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + #[must_use] pub fn key_config(self, key_config: &'a [u8; 0x16C]) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { key_config: Some(key_config), @@ -144,6 +155,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + #[must_use] pub fn joystick_config(self, joystick_config: &'a [u8; 0x38]) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { joystick_config: Some(joystick_config), @@ -151,6 +163,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + #[must_use] pub fn symbol_chat(self, symbol_chat: &'a [u8; 1248]) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { symbol_chat: Some(symbol_chat), @@ -158,6 +171,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + #[must_use] pub fn tech_menu(self, tech_menu: &'a [u8; 40]) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { tech_menu: Some(tech_menu), @@ -165,6 +179,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { } } + #[must_use] pub fn option_flags(self, option_flags: u32) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { option_flags: Some(option_flags), diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index ac8420d..950e088 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -1003,7 +1003,7 @@ impl ItemManager { inventory.add_item(InventoryItem::Individual(IndividualInventoryItem { entity_id, item_id, - item: ItemDetail::Weapon(weapon.clone()), + item: ItemDetail::Weapon(weapon), })); entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?; @@ -1066,9 +1066,9 @@ impl ItemManager { TradeItem::Stacked(item_id, amount) => { let stacked_inventory_item = src_inventory .get_item_by_id(*item_id) - .ok_or_else(|| TradeError::InvalidItemId(*item_id))? + .ok_or(TradeError::InvalidItemId(*item_id))? .stacked() - .ok_or_else(|| TradeError::InvalidItemId(*item_id))?; + .ok_or(TradeError::InvalidItemId(*item_id))?; match dest_inventory.space_for_stacked_item(&stacked_inventory_item.tool, *amount) { SpaceForStack::Yes(YesThereIsSpace::ExistingStack) => { Ok(acc) diff --git a/src/ship/map/area.rs b/src/ship/map/area.rs index 1bbc2b6..344c8a6 100644 --- a/src/ship/map/area.rs +++ b/src/ship/map/area.rs @@ -293,6 +293,7 @@ pub struct MapAreaLookupBuilder { } impl MapAreaLookupBuilder { + #[must_use] pub fn add(mut self, value: u16, map_area: MapArea) -> MapAreaLookupBuilder { self.map_areas.insert(value, map_area); self diff --git a/src/ship/map/maps.rs b/src/ship/map/maps.rs index e1558d8..aaa63b9 100644 --- a/src/ship/map/maps.rs +++ b/src/ship/map/maps.rs @@ -277,9 +277,9 @@ impl Maps { enemy_data.append(&mut enemy_data_from_map_data(map_variant, &room_mode.episode())); enemy_data }), - object_data: map_variants.iter().map(|map_variant| { + object_data: map_variants.iter().flat_map(|map_variant| { objects_from_map_data(map_variant.obj_file().into(), &room_mode.episode(), &map_variant.map) - }).flatten().collect(), + }).collect(), map_variants, }; maps diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs index fcceb43..a417c6f 100644 --- a/src/ship/packet/handler/direct_message.rs +++ b/src/ship/packet/handler/direct_message.rs @@ -81,9 +81,9 @@ where { let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?; let room = rooms.get_mut(room_id.0) - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? .as_mut() - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; let monster = room.maps.enemy_by_id(request_item.enemy_id as usize)?; if monster.dropped_item { @@ -187,9 +187,9 @@ EG: EntityGateway { let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?; let room = rooms.get_mut(room_id.0) - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? .as_mut() - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; let box_object = room.maps.object_by_id(box_drop_request.object_id as usize)?; if box_object.dropped_item { @@ -297,13 +297,12 @@ where }; Ok(Box::new(other_clients_in_area.into_iter() - .map(move |c| { + .flat_map(move |c| { bank_action_pkts.clone().into_iter() .map(move |pkt| { (c.client, pkt) }) }) - .flatten() )) } @@ -319,9 +318,9 @@ pub async fn shop_request(id: ClientId, let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?; let room = rooms.get(room_id.0) - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? .as_ref() - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; let level = level_table.get_level_from_exp(client.character.char_class, client.character.exp) as usize; let shop_list = match shop_request.shop_type { SHOP_OPTION_WEAPON => { diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs index 1f405e4..c39ba73 100644 --- a/src/ship/packet/handler/message.rs +++ b/src/ship/packet/handler/message.rs @@ -20,9 +20,9 @@ pub async fn request_exp(id: ClientId, let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?; let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?; let room = rooms.get_mut(room_id.0) - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? .as_mut() - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; let monster = room.maps.enemy_by_id(request_exp.enemy_id as usize)?; let monster_stats = room.monster_stats.get(&monster.monster).ok_or(ShipError::UnknownMonster(monster.monster))?; @@ -76,9 +76,9 @@ where let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?; let room = rooms.get_mut(room_id.0) - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? .as_mut() - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; + .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?; let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; @@ -99,9 +99,9 @@ pub fn drop_coordinates(id: ClientId, let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?; let room = rooms.get(room_id.0) - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? .as_ref() - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; client.item_drop_location = Some(ItemDropLocation { map_area: *room.map_areas.get_area_map(drop_coordinates.map_area)?, @@ -140,7 +140,7 @@ where let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; Ok(Box::new(clients_in_area.into_iter() - .map(move |c| { + .flat_map(move |c| { std::iter::once((c.client, SendShipPacket::Message(Message::new(GameMessage::DropSplitStack(dropped_meseta_pkt.clone()))))) .chain( if c.client != id { @@ -153,7 +153,6 @@ where } ) }) - .flatten() )) } else { @@ -191,9 +190,9 @@ pub fn update_player_position(id: ClientId, let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; if let Ok(room_id) = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() }) { let room = rooms.get(room_id.0) - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))? .as_ref() - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; match &message.msg { GameMessage::PlayerChangedMap(p) => { diff --git a/src/ship/packet/handler/quest.rs b/src/ship/packet/handler/quest.rs index 41412ac..1e2e569 100644 --- a/src/ship/packet/handler/quest.rs +++ b/src/ship/packet/handler/quest.rs @@ -81,8 +81,8 @@ pub fn load_quest(id: ClientId, questmenuselect: &QuestMenuSelect, quests: &Ques let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?; let room = rooms.get_mut(room_id.0) - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?.as_mut() - .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?.as_mut() + .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; room.maps.set_quest_data(quest.enemies.clone(), quest.objects.clone()); room.map_areas = quest.map_areas.clone(); @@ -95,9 +95,9 @@ pub fn load_quest(id: ClientId, questmenuselect: &QuestMenuSelect, quests: &Ques client.done_loading_quest = false; } }); - Ok(Box::new(area_clients.into_iter().map(move |c| { + Ok(Box::new(area_clients.into_iter().flat_map(move |c| { vec![(c.client, SendShipPacket::QuestHeader(bin.clone())), (c.client, SendShipPacket::QuestHeader(dat.clone()))] - }).flatten())) + }))) } pub fn quest_file_request(id: ClientId, quest_file_request: &QuestFileRequest, quests: &QuestList) -> Result + Send>, ShipError> { diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index 60339bb..33d4753 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -156,14 +156,14 @@ pub fn done_bursting(id: ClientId, } let area_client = client_location.get_local_client(id).unwrap(); // TODO: unwrap Box::new(client_location.get_client_neighbors(id).unwrap().into_iter() // TODO: unwrap - .map(move |client| { + .flat_map(move |client| { vec![ (client.client, SendShipPacket::Message(Message::new(GameMessage::BurstDone(BurstDone { client: area_client.local_client.id(), target: 0 })))), ] - }).flatten()) + })) } pub fn request_room_list(id: ClientId, diff --git a/src/ship/packet/handler/trade.rs b/src/ship/packet/handler/trade.rs index 7792b4e..040bc29 100644 --- a/src/ship/packet/handler/trade.rs +++ b/src/ship/packet/handler/trade.rs @@ -481,7 +481,7 @@ where let clients_in_room = client_location.get_all_clients_by_client(id)?; let traded_item_packets = traded_items .into_iter() - .map(|item| { + .flat_map(|item| { match item.item_detail { ItemToTradeDetail::Individual(item_detail) => { [ @@ -503,8 +503,7 @@ where }, } }) - .flatten() - .map(move |packet| { + .flat_map(move |packet| { clients_in_room .clone() .into_iter() @@ -521,8 +520,7 @@ where _ => Some((client.client, SendShipPacket::Message(Message::new(packet.clone())))) } }) - }) - .flatten(); + }); let close_trade = vec![ (this.client(), SendShipPacket::TradeSuccessful(TradeSuccessful::default())), (other.client(), SendShipPacket::TradeSuccessful(TradeSuccessful::default())) diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 98b26ca..8efac0f 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -355,31 +355,37 @@ impl Default for ShipServerStateBuilder { } impl ShipServerStateBuilder { + #[must_use] pub fn gateway(mut self, entity_gateway: EG) -> ShipServerStateBuilder { self.entity_gateway = Some(entity_gateway); self } + #[must_use] pub fn name(mut self, name: String) -> ShipServerStateBuilder { self.name = Some(name); self } + #[must_use] pub fn ip(mut self, ip: Ipv4Addr) -> ShipServerStateBuilder { self.ip = Some(ip); self } + #[must_use] pub fn port(mut self, port: u16) -> ShipServerStateBuilder { self.port = Some(port); self } + #[must_use] pub fn auth_token(mut self, auth_token: AuthToken) -> ShipServerStateBuilder { self.auth_token = Some(auth_token); self } + #[must_use] pub fn blocks(mut self, num_blocks: usize) -> ShipServerStateBuilder { self.num_blocks = num_blocks; self diff --git a/src/ship/trade.rs b/src/ship/trade.rs index 9f600a8..39d7d0e 100644 --- a/src/ship/trade.rs +++ b/src/ship/trade.rs @@ -107,7 +107,7 @@ impl TradeState { where F: Fn(&mut ClientTradeState, &mut ClientTradeState) -> T { - let mut c1 = self.trades.get(client).ok_or_else(|| TradeStateError::ClientNotInTrade(*client))?.borrow_mut(); + let mut c1 = self.trades.get(client).ok_or(TradeStateError::ClientNotInTrade(*client))?.borrow_mut(); let mut c2 = self.trades.get(&c1.other_client).ok_or(TradeStateError::ClientNotInTrade(c1.other_client))?.borrow_mut(); // sanity check -- 2.36.0 From 51d706fc6592e395b0e6b4cc279945d111b8dab8 Mon Sep 17 00:00:00 2001 From: jake Date: Wed, 29 Dec 2021 19:04:22 -0700 Subject: [PATCH 34/34] clippy demands more --- src/ship/map/enemy.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ship/map/enemy.rs b/src/ship/map/enemy.rs index 6cbe07e..b5efd7c 100644 --- a/src/ship/map/enemy.rs +++ b/src/ship/map/enemy.rs @@ -316,6 +316,7 @@ impl MapEnemy { } } + #[must_use] pub fn set_shiny(self) -> MapEnemy { MapEnemy { shiny: true, @@ -337,6 +338,7 @@ impl MapEnemy { TODO: distinguish between a `random` rare monster and a `set/guaranteed` rare monster? (does any acceptable quest even have this?) guaranteed rare monsters don't count towards the limit */ + #[must_use] pub fn set_rare_appearance(self) -> MapEnemy { match (self.monster, self.map_area.to_episode()) { (MonsterType::RagRappy, Episode::One) => {MapEnemy {monster: MonsterType::AlRappy, shiny:true, ..self}}, @@ -357,6 +359,7 @@ impl MapEnemy { } // in theory this should only be called on monsters we know can have rare types + #[must_use] pub fn roll_appearance_for_mission(self, rare_monster_table: &RareMonsterAppearTable) -> MapEnemy { if rare_monster_table.roll_appearance(&self.monster) { return self.set_rare_appearance() -- 2.36.0