1
+ import { execSync } from 'child_process' ;
1
2
import sqlite3 from 'better-sqlite3' ;
2
3
import fs from 'fs' ;
3
4
import yaml from 'js-yaml' ;
@@ -6,17 +7,17 @@ import { Beco } from './beco';
6
7
7
8
let parseArgs = require ( 'minimist' ) ;
8
9
let argv = parseArgs ( process . argv ) ;
9
- if ( ! argv . d || ! argv . b || ! argv . e ) {
10
+ if ( ! argv . e || ! argv . r ) {
10
11
console . log ( "Error: Must specify paths to directories with " ) ;
11
- console . log ( " -d Banc extracted YAML files" ) ;
12
- console . log ( " -b field map area beco files" ) ;
13
12
console . log ( " -e Ecosystem json files" ) ;
14
- console . log ( " e.g. % ts-node build.ts -d path/to/Banc -b path/to/beco -e path/to/Ecosystem" )
13
+ console . log ( " -r Bare game romfs" ) ;
14
+ console . log ( " e.g. % ts-node build.ts -r path/to/romfs -e tools" )
15
15
process . exit ( 1 ) ;
16
16
}
17
- const totkData = argv . d
18
- const becoPath = argv . b ;
19
17
const ecoPath = argv . e ;
18
+ const romfsPath = argv . r ;
19
+ const totkData = path . join ( romfsPath , 'Banc' ) ;
20
+ const becoPath = path . join ( romfsPath , 'Ecosystem' , 'FieldMapArea' ) ;
20
21
21
22
fs . rmSync ( 'map.db.tmp' , { force : true } ) ;
22
23
const db = sqlite3 ( 'map.db.tmp' ) ;
@@ -85,14 +86,29 @@ const LOCATIONS = JSON.parse(fs.readFileSync('LocationMarker.json', 'utf8'))
85
86
const KOROKS = JSON . parse ( fs . readFileSync ( 'koroks_id.json' , 'utf8' ) )
86
87
const DROP_TABLES = JSON . parse ( fs . readFileSync ( 'drop_tables.json' , 'utf8' ) )
87
88
89
+ const BCETT_YAML_SUFFIXES = / \. b c e t t \. b ? y m l ( \. z s ) ? $ / ;
90
+
88
91
const DropTableDefault = "Default" ;
89
92
const DROP_TYPE_ACTOR = "Actor" ;
90
93
const DROP_TYPE_TABLE = "Table" ;
91
94
92
- const BecoGround = new Beco ( path . join ( becoPath , 'Ground.beco' ) ) ;
93
- const BecoMinus = new Beco ( path . join ( becoPath , 'MinusField.beco' ) ) ;
94
- const BecoSky = new Beco ( path . join ( becoPath , 'Sky.beco' ) ) ;
95
- const BecoCave = new Beco ( path . join ( becoPath , 'Cave.beco' ) ) ;
95
+ const getZsDicPath = ( function ( ) {
96
+ // Only call these tools when we need to use them, only extract zsdics once
97
+ let zsDicPath : string = "" ;
98
+ return function ( ) : string {
99
+ if ( ! zsDicPath ) {
100
+ zsDicPath = fs . mkdtempSync ( 'zsdicpack' ) ;
101
+ execSync ( `zstd -d "${ romfsPath } /Pack/ZsDic.pack.zs" -o "${ zsDicPath } /ZsDic.pack"` ) ;
102
+ execSync ( `sarc x --directory "${ zsDicPath } " "${ zsDicPath } /ZsDic.pack"` ) ;
103
+ }
104
+ return zsDicPath ;
105
+ } ;
106
+ } ) ( ) ;
107
+
108
+ const BecoGround = new Beco ( readRawBeco ( 'Ground' ) ) ;
109
+ const BecoMinus = new Beco ( readRawBeco ( 'MinusField' ) ) ;
110
+ const BecoSky = new Beco ( readRawBeco ( 'Sky' ) ) ;
111
+ const BecoCave = new Beco ( readRawBeco ( 'Cave' ) ) ;
96
112
97
113
// Should probably be yaml not json for consistency
98
114
const Ecosystem = Object . fromEntries ( [ 'Cave' , 'Ground' , 'MinusField' , 'Sky' ] . map ( name => {
@@ -192,6 +208,27 @@ function parseHash(hash: string) {
192
208
return '0x' + BigInt ( hash ) . toString ( 16 ) . padStart ( 16 , '0' ) ;
193
209
}
194
210
211
+ function readRawBeco ( name : string ) : Buffer {
212
+ let filePath = path . join ( becoPath , name + '.beco' ) ;
213
+ if ( fs . existsSync ( filePath ) ) {
214
+ return fs . readFileSync ( filePath ) ;
215
+ } else if ( fs . existsSync ( filePath + '.zs' ) ) {
216
+ return execSync ( `zstd -D "${ getZsDicPath ( ) } /zs.zsdic" -d ${ filePath } .zs -c` , { maxBuffer : 1073741824 } ) ;
217
+ }
218
+ throw Error ( `No beco file found for ${ name } ` ) ;
219
+ }
220
+
221
+ function readRawYaml ( filePath : string ) : string {
222
+ if ( filePath . endsWith ( '.yml' ) ) {
223
+ return fs . readFileSync ( filePath , 'utf-8' ) . toString ( ) ;
224
+ } else if ( filePath . endsWith ( '.byml' ) ) {
225
+ return execSync ( `byml_to_yml ${ filePath } -` , { maxBuffer : 1073741824 } ) . toString ( ) ;
226
+ } else if ( filePath . endsWith ( '.byml.zs' ) ) {
227
+ return execSync ( `zstd -D "${ getZsDicPath ( ) } /bcett.byml.zsdic" -d ${ filePath } -c | byml_to_yml - -` , { maxBuffer : 1073741824 } ) . toString ( ) ;
228
+ }
229
+ throw Error ( `No yml file found at ${ filePath } ` ) ;
230
+ }
231
+
195
232
function getKorokType ( hideType : number | undefined , name : string ) {
196
233
if ( name == 'KorokCarryProgressKeeper' ) {
197
234
return 'Korok Friends' ;
@@ -215,9 +252,7 @@ function getKorokType(hideType: number | undefined, name: string) {
215
252
function processBanc ( filePath : string , mapType : string , mapName : string ) {
216
253
let doc : any = null ;
217
254
try {
218
- doc = yaml . load ( fs . readFileSync ( filePath , 'utf-8' ) ,
219
- { schema : schema }
220
- ) ;
255
+ doc = yaml . load ( readRawYaml ( filePath ) , { schema : schema } ) ;
221
256
} catch ( e : any ) {
222
257
console . log ( "Error: " , e ) ;
223
258
process . exit ( 1 ) ;
@@ -443,13 +478,13 @@ function processBancs() {
443
478
const dirPath = path . join ( totkData , field ) ;
444
479
let files = fs . readdirSync ( dirPath ) ;
445
480
for ( const file of files ) {
446
- if ( ! file . endsWith ( '.bcett.yml' ) )
481
+ if ( ! file . match ( BCETT_YAML_SUFFIXES ) )
447
482
continue ;
448
483
let filePath = path . join ( dirPath , file ) ;
449
484
450
485
const fieldParts = field . split ( "/" ) ;
451
486
let mapName = file
452
- . replace ( ".bcett.yml" , "" )
487
+ . replace ( BCETT_YAML_SUFFIXES , "" )
453
488
. replace ( "_Static" , "" )
454
489
. replace ( "_Dynamic" , "" ) ;
455
490
const mapType = fieldParts [ 0 ] ;
@@ -463,12 +498,12 @@ function processBancs() {
463
498
for ( const mapType of [ "SmallDungeon" , "LargeDungeon" , "NormalStage" ] ) {
464
499
const dirPath = path . join ( totkData , mapType ) ;
465
500
for ( const file of fs . readdirSync ( dirPath ) ) {
466
- if ( ! file . endsWith ( '.bcett.yml' ) )
501
+ if ( ! file . match ( BCETT_YAML_SUFFIXES ) )
467
502
continue ;
468
503
469
504
const filePath = path . join ( dirPath , file ) ;
470
505
const mapName = file
471
- . replace ( ".bcett.yml" , "" )
506
+ . replace ( BCETT_YAML_SUFFIXES , "" )
472
507
. replace ( "_Static" , "" )
473
508
. replace ( "_Dynamic" , "" ) ;
474
509
processBanc ( filePath , mapType , mapName ) ;
@@ -496,8 +531,7 @@ function processRecycleBox() {
496
531
console . log ( "process recyclebox: " , filePath )
497
532
let doc : any = null ;
498
533
try {
499
- doc = yaml . load ( fs . readFileSync ( filePath , 'utf-8' ) ,
500
- { schema : schema } ) ;
534
+ doc = yaml . load ( readRawYaml ( filePath ) , { schema : schema } ) ;
501
535
} catch ( e : any ) {
502
536
console . log ( "Error: " , e ) ;
503
537
process . exit ( 1 ) ;
0 commit comments