1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use std::collections::HashMap;
use std::io;
use super::super::item_def::ItemDefinition;
use crate::{
Cache, CacheError,
LinkedListExt,
codec,
cache::archive::ArchiveData
};
pub struct ItemLoader {
pub items: HashMap<u16, ItemDefinition>
}
impl ItemLoader {
#[inline]
pub fn new(cache: &Cache) -> Result<Self, CacheError> {
let index_id = 2;
let archive_id = 10;
let mut buffer = &cache.read(255, index_id)?.to_vec()[..];
let mut buffer = &codec::decode(&mut buffer)?[..];
let archives = ArchiveData::decode(&mut buffer)?;
let entry_count = archives[archive_id - 1].entry_count();
let mut buffer = &cache.read(2, 10)?.to_vec()[..];
let buffer = codec::decode(&mut buffer)?;
let items = decode_item_data(&buffer, entry_count)?;
Ok(Self { items })
}
#[inline]
pub fn load(&self, id: u16) -> Option<&ItemDefinition> {
self.items.get(&id)
}
}
fn decode_item_data(buffer: &[u8], entry_count: usize) -> io::Result<HashMap<u16, ItemDefinition>> {
let chunks = buffer[buffer.len() - 1] as usize;
let mut items = HashMap::new();
let mut cached_chunks = Vec::new();
let mut read_ptr = buffer.len() - 1 - chunks * entry_count * 4;
for _ in 0..chunks {
let mut chunk_size = 0;
for entry_id in 0..entry_count {
let mut bytes = [0; 4];
bytes.copy_from_slice(&buffer[read_ptr..read_ptr + 4]);
let delta = i32::from_be_bytes(bytes);
read_ptr += 4;
chunk_size += delta;
cached_chunks.push((entry_id as u16, chunk_size as usize));
}
}
read_ptr = 0;
for (entry_id, chunk_size) in cached_chunks {
let buf = buffer[read_ptr..read_ptr + chunk_size].to_vec();
let item_def = ItemDefinition::new(entry_id, &buf)?;
items.insert(entry_id, item_def);
read_ptr += chunk_size;
}
Ok(items)
}