rscache/loader/
osrs.rs

1use std::collections::{
2    hash_map::{self, Entry},
3    HashMap,
4};
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9use crate::{
10    definition::osrs::{
11        Definition, FetchDefinition, ItemDefinition, LocationDefinition, MapDefinition,
12        NpcDefinition, ObjectDefinition,
13    },
14    Cache,
15};
16
17/// Loads all item definitions from the current cache.
18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
19#[derive(Clone, Eq, PartialEq, Debug, Default)]
20pub struct ItemLoader(HashMap<u16, ItemDefinition>);
21
22impl_osrs_loader!(ItemLoader, ItemDefinition, index_id: 2, archive_id: 10);
23
24/// Loads all npc definitions from the current cache.
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26#[derive(Clone, Eq, PartialEq, Debug, Default)]
27pub struct NpcLoader(HashMap<u16, NpcDefinition>);
28
29impl_osrs_loader!(NpcLoader, NpcDefinition, index_id: 2, archive_id: 9);
30
31/// Loads all object definitions from the current cache.
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33#[derive(Clone, Eq, PartialEq, Debug, Default)]
34pub struct ObjectLoader(HashMap<u16, ObjectDefinition>);
35
36impl_osrs_loader!(ObjectLoader, ObjectDefinition, index_id: 2, archive_id: 6);
37
38/// Loads maps definitions lazily from the current cache.
39#[derive(Debug)]
40pub struct MapLoader<'cache> {
41    cache: &'cache Cache,
42    maps: HashMap<u16, MapDefinition>,
43}
44
45impl<'cache> MapLoader<'cache> {
46    /// Make a new `MapLoader`.
47    ///
48    /// This takes a `Cache` by references with a `'cache` lifetime.
49    /// All the map definitions are loaded lazily where the `&'cache Cache` is used
50    /// to cache them internally on load.
51    pub fn new(cache: &'cache Cache) -> Self {
52        Self {
53            cache,
54            maps: HashMap::new(),
55        }
56    }
57
58    pub fn load(&mut self, id: u16) -> crate::Result<&MapDefinition> {
59        if let Entry::Vacant(entry) = self.maps.entry(id) {
60            let x = id >> 8;
61            let y = id & 0xFF;
62
63            let map_archive = self.cache.archive_by_name(5, format!("m{}_{}", x, y))?;
64            let buffer = self.cache.read_archive(map_archive)?.decode()?;
65
66            entry.insert(MapDefinition::new(id, &buffer)?);
67        }
68
69        Ok(&self.maps[&id])
70    }
71}
72
73/// Loads location definitions lazily from the current cache.
74#[derive(Debug)]
75pub struct LocationLoader<'cache> {
76    cache: &'cache Cache,
77    locations: HashMap<u16, LocationDefinition>,
78}
79
80impl<'cache> LocationLoader<'cache> {
81    /// Make a new `LocationLoader`.
82    ///
83    /// This takes a `Cache` by references with a `'cache` lifetime.
84    /// All the location definitions are loaded lazily where the `&'cache Cache` is used
85    /// to cache them internally on load.
86    pub fn new(cache: &'cache Cache) -> Self {
87        Self {
88            cache,
89            locations: HashMap::new(),
90        }
91    }
92
93    /// Loads the location data for a particular region.
94    ///
95    /// Also takes a `keys: [u32; 4]` because the location archive is encrypted
96    /// with XTEA. The buffer is automatically decoded with the given keys.
97    pub fn load(&mut self, id: u16, keys: &[u32; 4]) -> crate::Result<&LocationDefinition> {
98        if let Entry::Vacant(entry) = self.locations.entry(id) {
99            let x = id >> 8;
100            let y = id & 0xFF;
101
102            let loc_archive = self.cache.archive_by_name(5, format!("l{}_{}", x, y))?;
103            let buffer = self
104                .cache
105                .read_archive(loc_archive)?
106                .with_xtea_keys(*keys)
107                .decode()?;
108
109            entry.insert(LocationDefinition::new(id, &buffer)?);
110        }
111
112        Ok(&self.locations[&id])
113    }
114}
115