From 2a30ac1bd961f2ce9ef3f2773c04ad4c8f6edcbe Mon Sep 17 00:00:00 2001 From: not a cow <104355555+not-a-cowfr@users.noreply.github.com> Date: Sat, 13 Sep 2025 20:19:48 -0700 Subject: [PATCH 1/4] begin npc data --- src/lib.rs | 33 +++++++++++++++++++++++++++++++++ src/models/mod.rs | 9 +++++++++ src/models/npc.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 src/models/npc.rs diff --git a/src/lib.rs b/src/lib.rs index efd5f57..11c0917 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ use std::path::Path; use log::{trace, warn}; use models::enchantment::SkyblockEnchantment; use models::item::SkyblockItem; +use models::npc::SkyblockNpc; use models::pet::SkyblockPet; pub use models::{UpgradeCost, UpgradeType, enchantment, item, pet, recipe}; #[cfg(feature = "python")] @@ -43,6 +44,7 @@ struct RepoStructure { pub struct SkyblockRepo { pub enchantments: FxHashMap, pub items: FxHashMap, + pub npcs: FxHashMap, pub pets: FxHashMap, } @@ -68,6 +70,7 @@ impl SkyblockRepo { let mut repo = Self { enchantments: FxHashMap::default(), items: FxHashMap::default(), + npcs: FxHashMap::default(), pets: FxHashMap::default(), }; @@ -91,6 +94,11 @@ 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()))?; @@ -124,6 +132,16 @@ impl SkyblockRepo { self.items.get(&id.to_uppercase()).cloned() } + /// Retrieves a pet 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] @@ -144,6 +162,7 @@ impl SkyblockRepo { let mut repo = Self { enchantments: FxHashMap::default(), items: FxHashMap::default(), + npcs: FxHashMap::default(), pets: FxHashMap::default(), }; @@ -167,6 +186,10 @@ 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); @@ -204,6 +227,16 @@ impl SkyblockRepo { self.items.get(&id.to_uppercase()).cloned() } + /// Retrieves a pet 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] diff --git a/src/models/mod.rs b/src/models/mod.rs index 6e1d6c0..962f6fa 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize}; pub mod enchantment; pub mod item; +pub mod npc; pub mod pet; pub mod recipe; @@ -24,3 +25,11 @@ pub enum UpgradeType { Essence, Coins, } + +#[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, +} From 3445158940f13e8cdc05b669a42a4c3851d5d49a Mon Sep 17 00:00:00 2001 From: not a cow <104355555+not-a-cowfr@users.noreply.github.com> Date: Sat, 13 Sep 2025 20:27:06 -0700 Subject: [PATCH 2/4] fix comment --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 11c0917..2117c34 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -132,7 +132,7 @@ impl SkyblockRepo { self.items.get(&id.to_uppercase()).cloned() } - /// Retrieves a pet by its `internalId` + /// Retrieves an npc by its `internalId` #[must_use] #[inline] pub fn get_npc_by_id( @@ -227,7 +227,7 @@ impl SkyblockRepo { self.items.get(&id.to_uppercase()).cloned() } - /// Retrieves a pet by its `internalId` + /// Retrieves an npc by its `internalId` #[must_use] #[inline] pub fn get_npc_by_id( From fd409f50cf18ca389905742645791ed5b22170d6 Mon Sep 17 00:00:00 2001 From: not a cow <104355555+not-a-cowfr@users.noreply.github.com> Date: Sat, 20 Sep 2025 23:33:37 -0700 Subject: [PATCH 3/4] add shops --- src/lib.rs | 33 +++++++++++++++++++++++++++++++++ src/models/mod.rs | 1 + src/models/shop.rs | 31 +++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/models/shop.rs diff --git a/src/lib.rs b/src/lib.rs index 2117c34..bebfb8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ use models::enchantment::SkyblockEnchantment; use models::item::SkyblockItem; use models::npc::SkyblockNpc; use models::pet::SkyblockPet; +use models::shop::SkyblockShop; pub use models::{UpgradeCost, UpgradeType, enchantment, item, pet, recipe}; #[cfg(feature = "python")] use pyo3::exceptions::PyValueError; @@ -46,6 +47,7 @@ pub struct SkyblockRepo { pub items: FxHashMap, pub npcs: FxHashMap, pub pets: FxHashMap, + pub shops: FxHashMap, } #[cfg(feature = "python")] @@ -72,6 +74,7 @@ impl SkyblockRepo { items: FxHashMap::default(), npcs: FxHashMap::default(), pets: FxHashMap::default(), + shops: FxHashMap::default(), }; for path_name in structure.paths.values() { @@ -104,6 +107,11 @@ impl SkyblockRepo { .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); + }, | _ => continue, } } @@ -151,6 +159,16 @@ 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() + } } #[cfg(not(feature = "python"))] @@ -164,6 +182,7 @@ impl SkyblockRepo { items: FxHashMap::default(), npcs: FxHashMap::default(), pets: FxHashMap::default(), + shops: FxHashMap::default(), }; for path_name in structure.paths.values() { @@ -194,6 +213,10 @@ impl SkyblockRepo { 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); + }, #[cfg_attr(not(feature = "log"), allow(unused_variables))] | other => { #[cfg(feature = "log")] @@ -246,4 +269,14 @@ 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() + } } diff --git a/src/models/mod.rs b/src/models/mod.rs index 962f6fa..1042217 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -7,6 +7,7 @@ pub mod item; pub mod npc; pub mod pet; pub mod recipe; +pub mod shop; #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] #[cfg_attr(feature = "python", pyclass)] 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, +} From ebb0d95b38ae4ecb333d2f7aa9d29c3a15e15a36 Mon Sep 17 00:00:00 2001 From: not a cow <104355555+not-a-cowfr@users.noreply.github.com> Date: Sat, 20 Sep 2025 23:50:43 -0700 Subject: [PATCH 4/4] add zones --- src/lib.rs | 33 +++++++++++++++++++++++++++++++++ src/models/mod.rs | 4 ++++ src/models/zone.rs | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/models/zone.rs diff --git a/src/lib.rs b/src/lib.rs index bebfb8b..87805f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ 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; @@ -48,6 +49,7 @@ pub struct SkyblockRepo { pub npcs: FxHashMap, pub pets: FxHashMap, pub shops: FxHashMap, + pub zones: FxHashMap, } #[cfg(feature = "python")] @@ -75,6 +77,7 @@ impl SkyblockRepo { npcs: FxHashMap::default(), pets: FxHashMap::default(), shops: FxHashMap::default(), + zones: FxHashMap::default(), }; for path_name in structure.paths.values() { @@ -112,6 +115,11 @@ impl SkyblockRepo { .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, } } @@ -169,6 +177,16 @@ impl SkyblockRepo { ) -> 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"))] @@ -183,6 +201,7 @@ impl SkyblockRepo { npcs: FxHashMap::default(), pets: FxHashMap::default(), shops: FxHashMap::default(), + zones: FxHashMap::default(), }; for path_name in structure.paths.values() { @@ -217,6 +236,10 @@ impl SkyblockRepo { 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")] @@ -279,4 +302,14 @@ impl SkyblockRepo { ) -> 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 1042217..11931cc 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -8,6 +8,7 @@ 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)] @@ -25,6 +26,9 @@ pub enum UpgradeType { Item, Essence, Coins, + Pelts, + Motes, + JacobMedal, } #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] 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, +}