@@ -4,6 +4,7 @@ import Packet from '#/io/Packet.js';
44import { getGroup } from '#/util/OpenRS2.js' ;
55import { unpackJs5Group } from '#/io/Js5Group.js' ;
66import { CompressionType } from '#/io/CompressionType.js' ;
7+ import { parseJs5ArchiveIndex as parseJs5ArchiveIndexCore , splitGroupFiles } from '#/io/Js5ArchiveIndex.js' ;
78
89export function readJs5Id ( packet : Packet , format : number ) : number {
910 if ( format >= 7 ) {
@@ -117,6 +118,14 @@ export async function readGroupBytes(
117118}
118119
119120export function ensureDir ( dirPath : string ) : void {
121+ if ( fs . existsSync ( dirPath ) ) {
122+ const stat = fs . statSync ( dirPath ) ;
123+ if ( stat . isDirectory ( ) ) {
124+ return ;
125+ }
126+ throw new Error ( `Path exists and is not a directory: ${ dirPath } ` ) ;
127+ }
128+
120129 fs . mkdirSync ( dirPath , { recursive : true } ) ;
121130}
122131
@@ -150,11 +159,85 @@ export function parsePackFile(packPath: string): Map<string, number> {
150159 return nameToId ;
151160}
152161
162+ export function parsePackFileById ( packPath : string ) : Map < number , string > {
163+ if ( ! fs . existsSync ( packPath ) ) {
164+ return new Map ( ) ;
165+ }
166+
167+ const content = fs . readFileSync ( packPath , 'utf-8' ) ;
168+ const idToName = new Map < number , string > ( ) ;
169+
170+ for ( const line of content . split ( '\n' ) ) {
171+ const trimmed = line . trim ( ) ;
172+ if ( trimmed . length === 0 || trimmed . startsWith ( '#' ) ) {
173+ continue ;
174+ }
175+
176+ const eq = trimmed . indexOf ( '=' ) ;
177+ if ( eq === - 1 ) {
178+ continue ;
179+ }
180+
181+ const id = parseInt ( trimmed . substring ( 0 , eq ) ) ;
182+ const name = trimmed . substring ( eq + 1 ) ;
183+
184+ if ( ! isNaN ( id ) && name . length > 0 ) {
185+ idToName . set ( id , name ) ;
186+ }
187+ }
188+
189+ return idToName ;
190+ }
191+
153192export type Js5ArchiveIndex = {
154193 groupIds : number [ ] ;
155194 fileIdsByGroup : Map < number , number [ ] > ;
156195} ;
157196
197+ export async function loadArchiveFileIds ( indexArchive : number , archive : number , openrs2 : boolean = true ) : Promise < number [ ] > {
198+ const indexPacked = await loadIndexPacked ( indexArchive , `data/cache/255/${ indexArchive } .dat` , openrs2 ) ;
199+ const indexData = unpackJs5Group ( indexPacked ) ;
200+ const { fileIdsByGroup } = parseJs5ArchiveIndexCore ( indexData ) ;
201+ const fileIds = fileIdsByGroup . get ( archive ) ;
202+
203+ if ( ! fileIds ) {
204+ throw new Error ( `Archive ${ archive } not found in index ${ indexArchive } ` ) ;
205+ }
206+
207+ return fileIds ;
208+ }
209+
210+ export type LoadedArchiveGroup = {
211+ fileIds : number [ ] ;
212+ groupPacked : Uint8Array ;
213+ groupUnpacked : Uint8Array ;
214+ files : Map < number , Uint8Array > ;
215+ } ;
216+
217+ export async function loadArchiveGroupFiles (
218+ indexArchive : number ,
219+ archive : number ,
220+ groupsDir : string ,
221+ openrs2 : boolean = true
222+ ) : Promise < LoadedArchiveGroup > {
223+ const fileIds = await loadArchiveFileIds ( indexArchive , archive , openrs2 ) ;
224+ const groupPacked = await readGroupBytes ( indexArchive , archive , groupsDir , openrs2 ) ;
225+
226+ if ( ! groupPacked ) {
227+ throw new Error ( `Missing group data for index ${ indexArchive } , archive ${ archive } ` ) ;
228+ }
229+
230+ const groupUnpacked = unpackJs5Group ( groupPacked ) ;
231+ const files = splitGroupFiles ( groupUnpacked , fileIds ) ;
232+
233+ return {
234+ fileIds,
235+ groupPacked,
236+ groupUnpacked,
237+ files
238+ } ;
239+ }
240+
158241export function parseJs5ArchiveIndex ( indexData : Uint8Array ) : Js5ArchiveIndex {
159242 const packet = new Packet ( indexData ) ;
160243
0 commit comments