diff --git a/src/lib.rs b/src/lib.rs index efd5f57..87805f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,10 @@ use std::path::Path; use log::{trace, warn}; use models::enchantment::SkyblockEnchantment; use models::item::SkyblockItem; +use models::npc::SkyblockNpc; use models::pet::SkyblockPet; +use models::shop::SkyblockShop; +use models::zone::SkyblockZone; pub use models::{UpgradeCost, UpgradeType, enchantment, item, pet, recipe}; #[cfg(feature = "python")] use pyo3::exceptions::PyValueError; @@ -43,7 +46,10 @@ struct RepoStructure { pub struct SkyblockRepo { pub enchantments: FxHashMap, pub items: FxHashMap, + pub npcs: FxHashMap, pub pets: FxHashMap, + pub shops: FxHashMap, + pub zones: FxHashMap, } #[cfg(feature = "python")] @@ -68,7 +74,10 @@ impl SkyblockRepo { let mut repo = Self { enchantments: FxHashMap::default(), items: FxHashMap::default(), + npcs: FxHashMap::default(), pets: FxHashMap::default(), + shops: FxHashMap::default(), + zones: FxHashMap::default(), }; for path_name in structure.paths.values() { @@ -91,11 +100,26 @@ impl SkyblockRepo { .map_err(|e| PyErr::new::(e.to_string()))?; repo.items.insert(parsed.internal_id.clone(), parsed); }, + | "npcs" => { + let parsed: SkyblockNpc = serde_json::from_str(&content) + .map_err(|e| PyErr::new::(e.to_string()))?; + repo.npcs.insert(parsed.internal_id.clone(), parsed); + }, | "pets" => { let parsed: SkyblockPet = serde_json::from_str(&content) .map_err(|e| PyErr::new::(e.to_string()))?; repo.pets.insert(parsed.internal_id.clone(), parsed); }, + | "shops" => { + let parsed: SkyblockShop = serde_json::from_str(&content) + .map_err(|e| PyErr::new::(e.to_string()))?; + repo.shops.insert(parsed.internal_id.clone(), parsed); + }, + | "zones" => { + let parsed: SkyblockZone = serde_json::from_str(&content) + .map_err(|e| PyErr::new::(e.to_string()))?; + repo.zones.insert(parsed.internal_id.clone(), parsed); + }, | _ => continue, } } @@ -124,6 +148,16 @@ impl SkyblockRepo { self.items.get(&id.to_uppercase()).cloned() } + /// Retrieves an npc by its `internalId` + #[must_use] + #[inline] + pub fn get_npc_by_id( + &self, + id: &str, + ) -> Option { + self.npcs.get(&id.to_uppercase()).cloned() + } + /// Retrieves a pet by its `internalId` #[must_use] #[inline] @@ -133,6 +167,26 @@ impl SkyblockRepo { ) -> Option { self.pets.get(&id.to_uppercase()).cloned() } + + /// Retrieves a shop by its `internalId` + #[must_use] + #[inline] + pub fn get_shop_by_id( + &self, + id: &str, + ) -> Option { + self.shops.get(&id.to_uppercase()).cloned() + } + + /// Retrieves a zone by its `internalId` + #[must_use] + #[inline] + pub fn get_zone_by_id( + &self, + id: &str, + ) -> Option { + self.zones.get(&id.to_uppercase()).cloned() + } } #[cfg(not(feature = "python"))] @@ -144,7 +198,10 @@ impl SkyblockRepo { let mut repo = Self { enchantments: FxHashMap::default(), items: FxHashMap::default(), + npcs: FxHashMap::default(), pets: FxHashMap::default(), + shops: FxHashMap::default(), + zones: FxHashMap::default(), }; for path_name in structure.paths.values() { @@ -167,10 +224,22 @@ impl SkyblockRepo { let parsed: SkyblockItem = serde_json::from_str(&content)?; repo.items.insert(parsed.internal_id.clone(), parsed); }, + | "npcs" => { + let parsed: SkyblockNpc = serde_json::from_str(&content)?; + repo.npcs.insert(parsed.internal_id.clone(), parsed); + }, | "pets" => { let parsed: SkyblockPet = serde_json::from_str(&content)?; repo.pets.insert(parsed.internal_id.clone(), parsed); }, + | "shops" => { + let parsed: SkyblockShop = serde_json::from_str(&content)?; + repo.shops.insert(parsed.internal_id.clone(), parsed); + }, + | "zones" => { + let parsed: SkyblockZone = serde_json::from_str(&content)?; + repo.zones.insert(parsed.internal_id.clone(), parsed); + }, #[cfg_attr(not(feature = "log"), allow(unused_variables))] | other => { #[cfg(feature = "log")] @@ -204,6 +273,16 @@ impl SkyblockRepo { self.items.get(&id.to_uppercase()).cloned() } + /// Retrieves an npc by its `internalId` + #[must_use] + #[inline] + pub fn get_npc_by_id( + &self, + id: &str, + ) -> Option { + self.npcs.get(&id.to_uppercase()).cloned() + } + /// Retrieves a pet by its `internalId` #[must_use] #[inline] @@ -213,4 +292,24 @@ impl SkyblockRepo { ) -> Option { self.pets.get(&id.to_uppercase()).cloned() } + + /// Retrieves a shop by its `internalId` + #[must_use] + #[inline] + pub fn get_shop_by_id( + &self, + id: &str, + ) -> Option { + self.shops.get(&id.to_uppercase()).cloned() + } + + /// Retrieves a zone by its `internalId` + #[must_use] + #[inline] + pub fn get_zone_by_id( + &self, + id: &str, + ) -> Option { + self.zones.get(&id.to_uppercase()).cloned() + } } diff --git a/src/models/mod.rs b/src/models/mod.rs index 6e1d6c0..11931cc 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -4,8 +4,11 @@ use serde::{Deserialize, Serialize}; pub mod enchantment; pub mod item; +pub mod npc; pub mod pet; pub mod recipe; +pub mod shop; +pub mod zone; #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] #[cfg_attr(feature = "python", pyclass)] @@ -23,4 +26,15 @@ pub enum UpgradeType { Item, Essence, Coins, + Pelts, + Motes, + JacobMedal, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[cfg_attr(feature = "python", pyclass)] +pub struct Coordinates { + pub x: f64, + pub y: f64, + pub z: f64, } diff --git a/src/models/npc.rs b/src/models/npc.rs new file mode 100644 index 0000000..2760731 --- /dev/null +++ b/src/models/npc.rs @@ -0,0 +1,46 @@ +#[cfg(feature = "python")] +use pyo3::pyclass; +use serde::{Deserialize, Serialize}; + +use crate::models::Coordinates; + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[serde(rename_all = "camelCase")] +#[cfg_attr(feature = "python", pyclass)] +pub struct SkyblockNpc { + #[serde(default)] + pub internal_id: String, + pub name: Option, + pub flags: Option, + pub location: Option, + pub visitor: Option, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[cfg_attr(feature = "python", pyclass)] +pub struct NpcFlags { + pub merchant: bool, + pub abiphone: bool, + pub garden: bool, + pub shop: bool, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[serde(rename_all = "camelCase")] +#[cfg_attr(feature = "python", pyclass)] +pub struct NpcLocation { + pub zone: Option, + pub coordinates: Option, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[serde(rename_all = "camelCase")] +#[cfg_attr(feature = "python", pyclass)] +pub struct NpcGardenVisitor { + pub rarity: String, + pub garden_level: u8, + pub desire: Option, + pub bonus: Option, + pub copper: Option, + pub farming_xp: Option, +} diff --git a/src/models/shop.rs b/src/models/shop.rs new file mode 100644 index 0000000..a0021ff --- /dev/null +++ b/src/models/shop.rs @@ -0,0 +1,31 @@ +use std::collections::BTreeMap; + +#[cfg(feature = "python")] +use pyo3::pyclass; +use serde::{Deserialize, Serialize}; + +use crate::UpgradeCost; + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[serde(rename_all = "camelCase")] +#[cfg_attr(feature = "python", pyclass)] +pub struct SkyblockShop { + #[serde(default)] + pub internal_id: String, + pub name: Option, + pub source: Option, + #[serde(default)] + pub slots: BTreeMap, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[cfg_attr(feature = "python", pyclass)] +pub struct InventorySlot { + pub material: Option, + pub name: Option, + pub lore: Option, + #[serde(default)] + pub cost: Vec, + #[serde(default)] + pub output: Vec, +} diff --git a/src/models/zone.rs b/src/models/zone.rs new file mode 100644 index 0000000..fa85da0 --- /dev/null +++ b/src/models/zone.rs @@ -0,0 +1,34 @@ +#[cfg(feature = "python")] +use pyo3::pyclass; +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +use crate::models::Coordinates; + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[serde(rename_all = "camelCase")] +#[cfg_attr(feature = "python", pyclass)] +pub struct SkyblockZone { + #[serde(default)] + pub internal_id: String, + pub name: Option, + pub source: Option, + pub discovery_text: Option, + #[serde(default)] + pub npcs: Vec, + #[serde(default)] + pub mobs: Vec, + #[serde(default)] + pub mob_drops: Vec, + #[serde(default)] + pub fairy_souls: Vec, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[cfg_attr(feature = "python", pyclass)] +pub struct FairySoul { + pub location: Option, + #[serde(default)] + pub number: i32, + pub coordinates: Option, +}