madden-franchise 3.6.0 → 3.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FranchiseEnum.js +4 -0
- package/FranchiseFile.js +13 -6
- package/FranchiseFileField.js +2 -2
- package/FranchiseFileSettings.js +8 -0
- package/FranchiseSchema.js +28 -11
- package/README.md +17 -0
- package/data/schemas/26/M26_660_1.gz +0 -0
- package/package.json +2 -2
- package/scripts/schema-generator-script-v2.js +44 -0
- package/services/schemaGeneratorV2.js +193 -0
- package/strategies/StrategyPicker.js +1 -0
package/FranchiseEnum.js
CHANGED
package/FranchiseFile.js
CHANGED
|
@@ -63,7 +63,7 @@ class FranchiseFile extends EventEmitter {
|
|
|
63
63
|
this._rawContents = fs.readFileSync(filePath);
|
|
64
64
|
|
|
65
65
|
/** @private @type {FileType} */
|
|
66
|
-
this._type = getFileType(this._rawContents);
|
|
66
|
+
this._type = getFileType(this._rawContents, this._settings);
|
|
67
67
|
|
|
68
68
|
/** @private @type {number} */
|
|
69
69
|
this._gameYear = this._type.year;
|
|
@@ -81,7 +81,7 @@ class FranchiseFile extends EventEmitter {
|
|
|
81
81
|
this.unpackedFileContents = unpackFile(this._rawContents, this._type);
|
|
82
82
|
|
|
83
83
|
if (this._type.format === Constants.FORMAT.FRANCHISE_COMMON) {
|
|
84
|
-
const newType = getFileType(this.unpackedFileContents);
|
|
84
|
+
const newType = getFileType(this.unpackedFileContents, this._settings);
|
|
85
85
|
this._type.year = newType.year;
|
|
86
86
|
this._gameYear = this._type.year;
|
|
87
87
|
this._expectedSchemaVersion = getSchemaMetadata(
|
|
@@ -121,7 +121,11 @@ class FranchiseFile extends EventEmitter {
|
|
|
121
121
|
).path;
|
|
122
122
|
|
|
123
123
|
try {
|
|
124
|
-
this.schemaList = new FranchiseSchema(schemaPath
|
|
124
|
+
this.schemaList = new FranchiseSchema(schemaPath, {
|
|
125
|
+
extraSchemas: this.settings.extraSchemas,
|
|
126
|
+
fileMap: this.settings.schemaFileMap,
|
|
127
|
+
useNewSchemaGeneration: this.settings.useNewSchemaGeneration
|
|
128
|
+
});
|
|
125
129
|
this.schemaList.on("schemas:done", () => {
|
|
126
130
|
resolve();
|
|
127
131
|
});
|
|
@@ -583,12 +587,13 @@ function _saveSync(destination, packedContents) {
|
|
|
583
587
|
/**
|
|
584
588
|
*
|
|
585
589
|
* @param {Buffer} data
|
|
590
|
+
* @param {FranchiseFileSettings} settings
|
|
586
591
|
* @returns {FileType}
|
|
587
592
|
*/
|
|
588
|
-
function getFileType(data) {
|
|
593
|
+
function getFileType(data, settings) {
|
|
589
594
|
const isDataCompressed = isCompressed(data);
|
|
590
595
|
const format = getFormat(data, isDataCompressed);
|
|
591
|
-
const year = getGameYear(data, isDataCompressed, format);
|
|
596
|
+
const year = settings?.gameYearOverride ?? getGameYear(data, isDataCompressed, format);
|
|
592
597
|
|
|
593
598
|
return {
|
|
594
599
|
format: format,
|
|
@@ -652,7 +657,7 @@ function getGameYear(data, isCompressed, format) {
|
|
|
652
657
|
max: 95,
|
|
653
658
|
},
|
|
654
659
|
{
|
|
655
|
-
year:
|
|
660
|
+
year: 26,
|
|
656
661
|
max: 999,
|
|
657
662
|
},
|
|
658
663
|
];
|
|
@@ -687,6 +692,8 @@ function getGameYear(data, isCompressed, format) {
|
|
|
687
692
|
} else if (data[0x2A] === 0x35) {
|
|
688
693
|
// M25 has year indicator in a different location
|
|
689
694
|
return 25;
|
|
695
|
+
} else if (data[0x2A] === 0x36) {
|
|
696
|
+
return 26;
|
|
690
697
|
} else {
|
|
691
698
|
const schemaMajor = getCompressedSchema(data).major;
|
|
692
699
|
const year = schemaMax.find((schema) => {
|
package/FranchiseFileField.js
CHANGED
|
@@ -149,7 +149,7 @@ class FranchiseFileField {
|
|
|
149
149
|
// return (formatted == 1 || (formatted.toString().toLowerCase() == 'true')) ? '1' : '0';
|
|
150
150
|
actualValue = (value == 1 || (value.toString().toLowerCase() == 'true'));
|
|
151
151
|
this._value = actualValue;
|
|
152
|
-
this._unformattedValue.setBits(this.offset.offset, actualValue, 1);
|
|
152
|
+
this._unformattedValue.setBits(this.offset.offset + (this.offset.length - 1), actualValue, 1);
|
|
153
153
|
break;
|
|
154
154
|
case 'float':
|
|
155
155
|
actualValue = parseFloat(value);
|
|
@@ -299,7 +299,7 @@ class FranchiseFileField {
|
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
case 'bool':
|
|
302
|
-
return unformatted.getBits(offset.offset, 1) ? true : false;
|
|
302
|
+
return unformatted.getBits(offset.offset + (offset.length - 1), 1) ? true : false;
|
|
303
303
|
case 'float':
|
|
304
304
|
// return utilService.bin2Float(unformatted);
|
|
305
305
|
return unformatted.getFloat32(offset.offset, offset.length);
|
package/FranchiseFileSettings.js
CHANGED
|
@@ -17,9 +17,17 @@ class FranchiseFileSettings {
|
|
|
17
17
|
/** @type {string | false} */
|
|
18
18
|
this.schemaDirectory = settings && settings.schemaDirectory ? settings.schemaDirectory : false;
|
|
19
19
|
/** @type {boolean} */
|
|
20
|
+
this.useNewSchemaGeneration = settings?.useNewSchemaGeneration ?? false;
|
|
21
|
+
/** @type {Object} */
|
|
22
|
+
this.schemaFileMap = settings?.schemaFileMap || {};
|
|
23
|
+
/** @type {Object[]} */
|
|
24
|
+
this.extraSchemas = settings?.extraSchemas || undefined;
|
|
25
|
+
/** @type {boolean} */
|
|
20
26
|
this.autoParse = settings && (settings.autoParse !== null && settings.autoParse !== undefined) ? settings.autoParse : true;
|
|
21
27
|
/** @type {boolean} */
|
|
22
28
|
this.autoUnempty = settings && (settings.autoUnempty !== null && settings.autoUnempty !== undefined) ? settings.autoUnempty : false;
|
|
29
|
+
/** @type {number} */
|
|
30
|
+
this.gameYearOverride = settings && (settings.gameYearOverride !== null && settings.gameYearOverride !== undefined) ? settings.gameYearOverride : null;
|
|
23
31
|
}
|
|
24
32
|
};
|
|
25
33
|
|
package/FranchiseSchema.js
CHANGED
|
@@ -4,6 +4,7 @@ const zlib = require('zlib');
|
|
|
4
4
|
const FranchiseEnum = require('./FranchiseEnum');
|
|
5
5
|
const EventEmitter = require('events').EventEmitter;
|
|
6
6
|
const schemaGenerator = require('./services/schemaGenerator');
|
|
7
|
+
const { generateSchemaV2 } = require('./services/schemaGeneratorV2');
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @typedef SchemaAttribute
|
|
@@ -30,12 +31,15 @@ const schemaGenerator = require('./services/schemaGenerator');
|
|
|
30
31
|
*/
|
|
31
32
|
|
|
32
33
|
class FranchiseSchema extends EventEmitter {
|
|
33
|
-
constructor (filePath) {
|
|
34
|
+
constructor (filePath, { useNewSchemaGeneration = false, extraSchemas = [], fileMap = {} } = {}) {
|
|
34
35
|
super();
|
|
35
36
|
this.schemas = [];
|
|
36
37
|
this.path = filePath;
|
|
38
|
+
this.useNewSchemaGeneration = useNewSchemaGeneration;
|
|
39
|
+
this.extraSchemas = extraSchemas;
|
|
40
|
+
this.fileMap = fileMap;
|
|
37
41
|
};
|
|
38
|
-
|
|
42
|
+
|
|
39
43
|
evaluate () {
|
|
40
44
|
const fileExtension = path.extname(this.path).toLowerCase();
|
|
41
45
|
|
|
@@ -109,15 +113,28 @@ class FranchiseSchema extends EventEmitter {
|
|
|
109
113
|
};
|
|
110
114
|
|
|
111
115
|
evaluateSchemaXml() {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
if (this.useNewSchemaGeneration) {
|
|
117
|
+
generateSchemaV2({
|
|
118
|
+
fileMap: this.fileMap,
|
|
119
|
+
extraSchemas: this.extraSchemas
|
|
120
|
+
}).then((schema) => {
|
|
121
|
+
this.schema = schema;
|
|
122
|
+
this.meta = schema.meta;
|
|
123
|
+
this.schemas = schema.schemas;
|
|
124
|
+
this.schemaMap = schema.schemaMap;
|
|
125
|
+
this.emit('schemas:done');
|
|
126
|
+
});
|
|
127
|
+
} else {
|
|
128
|
+
schemaGenerator.eventEmitter.on('schemas:done', (schema) => {
|
|
129
|
+
this.schema = schema;
|
|
130
|
+
this.meta = schema.meta;
|
|
131
|
+
this.schemas = schema.schemas;
|
|
132
|
+
this.schemaMap = schema.schemaMap;
|
|
133
|
+
this.emit('schemas:done');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
schemaGenerator.generate(this.path);
|
|
137
|
+
}
|
|
121
138
|
};
|
|
122
139
|
};
|
|
123
140
|
|
package/README.md
CHANGED
|
@@ -35,6 +35,7 @@ madden-franchise is a Madden franchise file parser written in NodeJS that allows
|
|
|
35
35
|
| Madden 23 | ✅ Full |
|
|
36
36
|
| Madden 24 | ✅ Full |
|
|
37
37
|
| Madden 25 | ✅ Full |
|
|
38
|
+
| Madden 26 | 🟡 Everything but CharacterVisuals |
|
|
38
39
|
|
|
39
40
|
### Quick Start
|
|
40
41
|
#### Initializing
|
|
@@ -65,6 +66,22 @@ madden-franchise is a Madden franchise file parser written in NodeJS that allows
|
|
|
65
66
|
// AUTO UNEMPTY - specify if you want the system to automatically determine if an empty field should become un-empty once you edit it.
|
|
66
67
|
// Warning: may have unintended side-effects if you batch import. Enable with caution.
|
|
67
68
|
autoUnempty: true/false [default: false]
|
|
69
|
+
|
|
70
|
+
// USE NEW SCHEMA GENERATION - use v2 schema generation, may cause issues
|
|
71
|
+
useNewSchemaGeneration: true/false [default: false]
|
|
72
|
+
|
|
73
|
+
// SCHEMA FIELD MAP - used with v2 schema generation - specify all schema input files. Object key should be either `main` to specify the main schema, or the name of the file as specified in the `<IncludeFile>`. Values should be absolute paths to the schema files.
|
|
74
|
+
schemaFileMap: {
|
|
75
|
+
main: '/abs/path/to/franchise-schemas.ftx',
|
|
76
|
+
'core-schemas': '/abs/path/to/core-schemas.ftx',
|
|
77
|
+
...
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// EXTRA SCHEMAS - used with v2 schema generation to specify extra schemas to include other than the defaults. Warning: if these are included, the default extra schemas will NOT be included and vice-versa.
|
|
81
|
+
extraSchemas: [...]
|
|
82
|
+
|
|
83
|
+
// GAME YEAR OVERRIDE - use to override the game year to adjust schema picker logic. Helpful for FTC files and other files that can't auto-detect year accurately.
|
|
84
|
+
gameYearOverride: number
|
|
68
85
|
}
|
|
69
86
|
|
|
70
87
|
#### Terminology
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "madden-franchise",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.2",
|
|
4
4
|
"description": "Tools to read a madden franchise file and get data from it",
|
|
5
5
|
"main": "FranchiseFile.js",
|
|
6
6
|
"scripts": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"bit-buffer": "^0.2.5",
|
|
17
|
+
"fast-xml-parser": "^5.2.5",
|
|
17
18
|
"node-xml-stream-parser": "^1.0.12"
|
|
18
19
|
},
|
|
19
20
|
"repository": {
|
|
@@ -22,7 +23,6 @@
|
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"chai": "^4.2.0",
|
|
25
|
-
"chai-eventemitter": "^1.1.1",
|
|
26
26
|
"mocha": "^9.1.4",
|
|
27
27
|
"proxyquire": "^2.1.3",
|
|
28
28
|
"sinon": "^7.5.0",
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// USAGE:
|
|
2
|
+
// node schema-generator-script.js [input file folder] [output file folder] [main schema name] [extra schema path]
|
|
3
|
+
const fs = require('fs/promises');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { gzipSync } = require('zlib');
|
|
6
|
+
const { generateSchemaV2 } = require('../services/schemaGeneratorV2');
|
|
7
|
+
|
|
8
|
+
let done = false;
|
|
9
|
+
|
|
10
|
+
(async () => {
|
|
11
|
+
const files = await fs.readdir(process.argv[2], { withFileTypes: true });
|
|
12
|
+
const schemas = files.filter(f => f.isFile() && f.name.endsWith('.FTX') && f.name !== 'football.FTX');
|
|
13
|
+
const mainSchemaName = process.argv[4] || 'franchise-schemas.FTX';
|
|
14
|
+
|
|
15
|
+
const main = schemas.find(f => f.name === mainSchemaName);
|
|
16
|
+
const otherSchemas = schemas
|
|
17
|
+
.filter(f => f.name !== mainSchemaName)
|
|
18
|
+
.reduce((acc, file) => {
|
|
19
|
+
const name = file.name.replace(/\.FTX$/i, '');
|
|
20
|
+
acc[name] = path.join(process.argv[2], file.name);
|
|
21
|
+
return acc;
|
|
22
|
+
}, {});
|
|
23
|
+
|
|
24
|
+
const schema = await generateSchemaV2({
|
|
25
|
+
fileMap: {
|
|
26
|
+
main: path.join(process.argv[2], main.name),
|
|
27
|
+
...otherSchemas
|
|
28
|
+
},
|
|
29
|
+
extraSchemas: process.argv[5] ? JSON.parse(await fs.readFile(process.argv[5], 'utf8')) : undefined
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const outputPath = process.argv[3] || __dirname;
|
|
33
|
+
const compressed = gzipSync(JSON.stringify(schema));
|
|
34
|
+
await fs.writeFile(path.join(outputPath, `M${schema.meta.gameYear}_${schema.meta.major}_${schema.meta.minor}.gz`), compressed);
|
|
35
|
+
done = true;
|
|
36
|
+
})();
|
|
37
|
+
|
|
38
|
+
function wait () {
|
|
39
|
+
if (!done) {
|
|
40
|
+
setTimeout(wait, 500);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
wait();
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
const fs = require('fs').promises;
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { XMLParser } = require('fast-xml-parser');
|
|
4
|
+
const FranchiseEnum = require('../FranchiseEnum');
|
|
5
|
+
const utilService = require('./utilService');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Parse FTX schema files with support for IncludeFile dependencies.
|
|
9
|
+
* @param {{main: string, [id:string]: string}} fileMap - { main: '/abs/path/to/main.FTX', ...otherName: '/abs/path/to/other.FTX' }
|
|
10
|
+
* @param {Object[]} [extraSchemas] - Optional array of extra schemas to include. If not included, will use defaults.
|
|
11
|
+
* @returns {Promise<Object>} - Parsed schema object
|
|
12
|
+
*/
|
|
13
|
+
async function generateSchemaV2({ fileMap, extraSchemas }) {
|
|
14
|
+
const parsedFiles = {};
|
|
15
|
+
const enums = [];
|
|
16
|
+
const schemas = [];
|
|
17
|
+
const schemaMap = {};
|
|
18
|
+
let schemaMeta = {};
|
|
19
|
+
|
|
20
|
+
if (!extraSchemas || extraSchemas.length === 0) {
|
|
21
|
+
// Load extra schemas if available
|
|
22
|
+
try {
|
|
23
|
+
const extraPath = path.join(__dirname, '../data/schemas/extra-schemas.json');
|
|
24
|
+
const extraRaw = await fs.readFile(extraPath, 'utf8');
|
|
25
|
+
extraSchemas = JSON.parse(extraRaw);
|
|
26
|
+
} catch (e) {
|
|
27
|
+
// ignore if not present
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Recursively parse a file and its includes (async)
|
|
32
|
+
async function parseFile(fileKey) {
|
|
33
|
+
if (parsedFiles[fileKey]) return;
|
|
34
|
+
const filePath = fileMap[fileKey];
|
|
35
|
+
if (!filePath) throw new Error(`Missing file mapping for: ${fileKey}`);
|
|
36
|
+
const xml = await fs.readFile(filePath, 'utf8');
|
|
37
|
+
const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '', allowBooleanAttributes: true, trimValues: false });
|
|
38
|
+
const doc = parser.parse(xml);
|
|
39
|
+
const root = doc.FranTkData;
|
|
40
|
+
if (!schemaMeta.databaseName && root.databaseName) {
|
|
41
|
+
schemaMeta = {
|
|
42
|
+
databaseName: root.databaseName,
|
|
43
|
+
dataMajorVersion: root.dataMajorVersion,
|
|
44
|
+
dataMinorVersion: root.dataMinorVersion
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Parse includes first
|
|
48
|
+
if (root.Includes && root.Includes.IncludeFile) {
|
|
49
|
+
const includes = Array.isArray(root.Includes.IncludeFile)
|
|
50
|
+
? root.Includes.IncludeFile
|
|
51
|
+
: [root.Includes.IncludeFile];
|
|
52
|
+
for (const inc of includes) {
|
|
53
|
+
let incKey = inc.fileName.replace(/\.FTX$/i, '');
|
|
54
|
+
if (!fileMap[incKey]) {
|
|
55
|
+
// Try all lowercase
|
|
56
|
+
incKey = incKey.toLowerCase();
|
|
57
|
+
if (!fileMap[incKey]) {
|
|
58
|
+
console.warn(`schemaGeneratorV2: Missing file mapping for include: ${incKey} in ${fileKey}`);
|
|
59
|
+
continue; // Suppress missing include mapping
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
await parseFile(incKey);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Parse enums and schemas
|
|
66
|
+
if (root.schemas) {
|
|
67
|
+
const items = Object.entries(root.schemas)
|
|
68
|
+
.flatMap(([tag, val]) => Array.isArray(val) ? val.map(v => ({ tag, ...v })) : [{ tag, ...val }]);
|
|
69
|
+
for (const item of items) {
|
|
70
|
+
if (item.tag === 'enum') {
|
|
71
|
+
const theEnum = new FranchiseEnum(item.name, item.assetId, item.isRecordPersistent);
|
|
72
|
+
theEnum._members = [];
|
|
73
|
+
if (item.attribute) {
|
|
74
|
+
const members = Array.isArray(item.attribute) ? item.attribute : [item.attribute];
|
|
75
|
+
for (const attr of members) {
|
|
76
|
+
theEnum.addMember && theEnum.addMember(attr.name, attr.idx, attr.value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
enums.push(theEnum);
|
|
80
|
+
} else if (item.tag === 'schema') {
|
|
81
|
+
const schema = {
|
|
82
|
+
assetId: item.assetId,
|
|
83
|
+
ownerAssetId: item.ownerAssetId,
|
|
84
|
+
numMembers: item.numMembers,
|
|
85
|
+
name: item.name,
|
|
86
|
+
base: item.base,
|
|
87
|
+
attributes: []
|
|
88
|
+
};
|
|
89
|
+
if (item.attribute) {
|
|
90
|
+
const attrs = Array.isArray(item.attribute) ? item.attribute : [item.attribute];
|
|
91
|
+
for (const attr of attrs) {
|
|
92
|
+
schema.attributes.push(parseAttribute(attr));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
schemas.push(schema);
|
|
96
|
+
schemaMap[schema.name] = schema;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
parsedFiles[fileKey] = true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Attribute parsing logic (copied from schemaGenerator.js)
|
|
104
|
+
function parseAttribute(attributeAttributes) {
|
|
105
|
+
return {
|
|
106
|
+
index: attributeAttributes.idx,
|
|
107
|
+
name: attributeAttributes.name,
|
|
108
|
+
type: attributeAttributes.type,
|
|
109
|
+
minValue: attributeAttributes.minValue,
|
|
110
|
+
maxValue: attributeAttributes.maxValue,
|
|
111
|
+
maxLength: attributeAttributes.maxLen,
|
|
112
|
+
default: getDefaultValue(attributeAttributes.default),
|
|
113
|
+
final: attributeAttributes.final,
|
|
114
|
+
enum: getEnum(attributeAttributes.type),
|
|
115
|
+
const: attributeAttributes.const
|
|
116
|
+
};
|
|
117
|
+
function getDefaultValue(defaultVal) {
|
|
118
|
+
if (!defaultVal) { return undefined; }
|
|
119
|
+
// Only replace XML entities, do not trim or modify whitespace at all
|
|
120
|
+
return defaultVal
|
|
121
|
+
.replace(/
/g, '\r')
|
|
122
|
+
.replace(/
/g, '\n')
|
|
123
|
+
.replace(/&/g, '&')
|
|
124
|
+
.replace(/>/g, '>')
|
|
125
|
+
.replace(/</g, '<')
|
|
126
|
+
.replace(/"/g, '"');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function getEnum(name) {
|
|
131
|
+
return enums.find(theEnum => theEnum.name === name);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function addExtraSchemas() {
|
|
135
|
+
if (!Array.isArray(extraSchemas)) return;
|
|
136
|
+
extraSchemas.forEach((schema) => {
|
|
137
|
+
if (!schemaMap[schema.name]) {
|
|
138
|
+
schema.attributes.filter((attrib) => {
|
|
139
|
+
return attrib.enum && !(attrib.enum instanceof FranchiseEnum);
|
|
140
|
+
}).forEach((attrib) => {
|
|
141
|
+
attrib.enum = getEnum(attrib.enum);
|
|
142
|
+
});
|
|
143
|
+
schemas.unshift(schema);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function calculateInheritedSchemas(schemaList) {
|
|
149
|
+
const schemasWithBase = schemaList.filter((schema) => schema.base && schema.base.indexOf('()') === -1);
|
|
150
|
+
schemasWithBase.forEach((schema) => {
|
|
151
|
+
if (schema.base && schema.base.indexOf('()') === -1) {
|
|
152
|
+
schema.originalAttributesOrder = schema.attributes;
|
|
153
|
+
const baseSchema = schemaList.find((schemaToSearch) => schemaToSearch.name === schema.base);
|
|
154
|
+
|
|
155
|
+
if (baseSchema) {
|
|
156
|
+
baseSchema.attributes.forEach((baseAttribute, index) => {
|
|
157
|
+
let oldIndex = schema.attributes.findIndex((schemaAttribute) => schemaAttribute?.name === baseAttribute?.name);
|
|
158
|
+
utilService.arrayMove(schema.attributes, oldIndex, index);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
await parseFile('main');
|
|
166
|
+
addExtraSchemas();
|
|
167
|
+
calculateInheritedSchemas(schemas);
|
|
168
|
+
|
|
169
|
+
// Set enum member lengths if needed
|
|
170
|
+
enums.forEach(e => e.setMemberLength && e.setMemberLength());
|
|
171
|
+
|
|
172
|
+
// Extract gameYear from databaseName
|
|
173
|
+
const majorVersion = schemaMeta.dataMajorVersion;
|
|
174
|
+
const minorVersion = schemaMeta.dataMinorVersion;
|
|
175
|
+
const databaseName = schemaMeta.databaseName;
|
|
176
|
+
const gameYearMatch = /Madden(\d{2})/.exec(databaseName);
|
|
177
|
+
const gameYear = gameYearMatch ? parseInt(gameYearMatch[1]) : null;
|
|
178
|
+
|
|
179
|
+
const root = {
|
|
180
|
+
meta: {
|
|
181
|
+
major: parseInt(majorVersion),
|
|
182
|
+
minor: parseInt(minorVersion),
|
|
183
|
+
gameYear
|
|
184
|
+
},
|
|
185
|
+
schemas,
|
|
186
|
+
schemaMap
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Return the plain object
|
|
190
|
+
return root;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
module.exports = { generateSchemaV2 };
|