madden-franchise 2.4.1 → 2.5.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/FranchiseFile.js +29 -23
- package/FranchiseSchema.js +7 -0
- package/package.json +3 -3
- package/services/schemaGenerator.js +119 -90
package/FranchiseFile.js
CHANGED
|
@@ -175,30 +175,20 @@ class FranchiseFile extends EventEmitter {
|
|
|
175
175
|
});
|
|
176
176
|
};
|
|
177
177
|
|
|
178
|
-
save(outputFilePath) {
|
|
179
|
-
return this.packFile(outputFilePath);
|
|
178
|
+
save(outputFilePath, options) {
|
|
179
|
+
return this.packFile(outputFilePath, options);
|
|
180
180
|
};
|
|
181
181
|
|
|
182
|
-
packFile(outputFilePath) {
|
|
182
|
+
packFile(outputFilePath, options) {
|
|
183
183
|
const that = this;
|
|
184
184
|
this.emit('saving');
|
|
185
185
|
|
|
186
186
|
return new Promise((resolve, reject) => {
|
|
187
187
|
this.unpackedFileContents = this.strategy.file.generateUnpackedContents(this.tables, this.unpackedFileContents);
|
|
188
|
-
// const changedTables = this.tables.filter((table) => { return table.isChanged; });
|
|
189
|
-
|
|
190
|
-
// for (let i = 0; i < changedTables.length; i++) {
|
|
191
|
-
// let table = changedTables[i];
|
|
192
|
-
// const header = that.unpackedFileContents.slice(0, table.offset);
|
|
193
|
-
// const trailer = that.unpackedFileContents.slice(table.offset + table.data.length);
|
|
194
|
-
// that.unpackedFileContents = Buffer.concat([header, table.hexData, trailer]);
|
|
195
|
-
|
|
196
|
-
// table.isChanged = false;
|
|
197
|
-
// }
|
|
198
188
|
|
|
199
189
|
let destination = outputFilePath ? outputFilePath : this.filePath;
|
|
200
190
|
|
|
201
|
-
_packFile(this.unpackedFileContents).then((data) => {
|
|
191
|
+
_packFile(this.unpackedFileContents, options).then((data) => {
|
|
202
192
|
const dataToSave = this.strategy.file.postPackFile(this.packedFileContents, data);
|
|
203
193
|
_save(destination, dataToSave, (err) => {
|
|
204
194
|
if (err) {
|
|
@@ -292,7 +282,7 @@ class FranchiseFile extends EventEmitter {
|
|
|
292
282
|
|
|
293
283
|
if (referencedTable) {
|
|
294
284
|
const fullBinary = utilService.getBinaryReferenceData(tableId, recordIndex);
|
|
295
|
-
const hex = utilService.bin2hex(fullBinary);
|
|
285
|
+
const hex = utilService.bin2hex(fullBinary).padStart(8, '0');
|
|
296
286
|
|
|
297
287
|
return this.tables.filter((table) => {
|
|
298
288
|
if (table.schema) {
|
|
@@ -300,6 +290,13 @@ class FranchiseFile extends EventEmitter {
|
|
|
300
290
|
return attribute.type === referencedTable.name;
|
|
301
291
|
});
|
|
302
292
|
}
|
|
293
|
+
else if (table.isArray && referencedTable.schema) {
|
|
294
|
+
// If the referenced table has a schema, we can check its base name.
|
|
295
|
+
// Some array table names are by the base name like EnumTable[] can contain AwardTypeEnumTableEntry
|
|
296
|
+
|
|
297
|
+
return table.name.slice(0, table.name.length - 2) === referencedTable.name
|
|
298
|
+
|| table.name.slice(0, table.name.length - 2) === referencedTable.schema.base;
|
|
299
|
+
}
|
|
303
300
|
else if (table.isArray) {
|
|
304
301
|
return table.name.slice(0, table.name.length - 2) === referencedTable.name;
|
|
305
302
|
}
|
|
@@ -339,15 +336,24 @@ function unpackFile (data, type) {
|
|
|
339
336
|
return zlib.inflateSync(data.slice(offset));
|
|
340
337
|
};
|
|
341
338
|
|
|
342
|
-
function _packFile (data) {
|
|
339
|
+
function _packFile (data, options) {
|
|
343
340
|
return new Promise((resolve, reject) => {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
resolve(
|
|
350
|
-
}
|
|
341
|
+
if (options && options.sync) {
|
|
342
|
+
const data = zlib.deflateSync(data, {
|
|
343
|
+
windowBits: 15
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
resolve(data);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
zlib.deflate(data, {
|
|
350
|
+
windowBits: 15
|
|
351
|
+
}, function (err, newData) {
|
|
352
|
+
if (err) reject(err);
|
|
353
|
+
|
|
354
|
+
resolve(newData);
|
|
355
|
+
});
|
|
356
|
+
}
|
|
351
357
|
});
|
|
352
358
|
};
|
|
353
359
|
|
package/FranchiseSchema.js
CHANGED
|
@@ -46,6 +46,7 @@ class FranchiseSchema extends EventEmitter {
|
|
|
46
46
|
this.meta = this.schema.meta;
|
|
47
47
|
this.schemas = this.schema.schemas;
|
|
48
48
|
this.schemaMap = {};
|
|
49
|
+
this.enumMap = {};
|
|
49
50
|
|
|
50
51
|
for (let i = 0; i < this.schemas.length; i++) {
|
|
51
52
|
const schema = this.schemas[i];
|
|
@@ -56,6 +57,7 @@ class FranchiseSchema extends EventEmitter {
|
|
|
56
57
|
|
|
57
58
|
if (attribute.enum) {
|
|
58
59
|
attribute.enum = new FranchiseEnum(attribute.enum);
|
|
60
|
+
this.enumMap[attribute.enum.name] = attribute.enum;
|
|
59
61
|
}
|
|
60
62
|
}
|
|
61
63
|
}
|
|
@@ -64,6 +66,11 @@ class FranchiseSchema extends EventEmitter {
|
|
|
64
66
|
const extraSchemas = schemaGenerator.getExtraSchemas();
|
|
65
67
|
extraSchemas.forEach((schema) => {
|
|
66
68
|
if (!this.schemaMap[schema.name]) {
|
|
69
|
+
schema.attributes.forEach((attrib) => {
|
|
70
|
+
if (attrib.enum) {
|
|
71
|
+
attrib.enum = new FranchiseEnum(this.enumMap[attrib.enum]);
|
|
72
|
+
}
|
|
73
|
+
})
|
|
67
74
|
this.schemas.unshift(schema);
|
|
68
75
|
this.schemaMap[schema.name] = schema;
|
|
69
76
|
addedExtraSchema = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "madden-franchise",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.2",
|
|
4
4
|
"description": "Tools to read a madden franchise file and get data from it",
|
|
5
5
|
"main": "FranchiseFile.js",
|
|
6
6
|
"scripts": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"author": "matthewpanetta",
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"xml-stream": "^0.
|
|
16
|
+
"node-xml-stream-parser": "^1.0.12"
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"chai": "^4.2.0",
|
|
24
24
|
"chai-eventemitter": "^1.1.1",
|
|
25
|
-
"mocha": "^
|
|
25
|
+
"mocha": "^9.1.4",
|
|
26
26
|
"proxyquire": "^2.1.3",
|
|
27
27
|
"sinon": "^7.5.0"
|
|
28
28
|
}
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
// USAGE:
|
|
2
|
-
// node schema-generator.js [input file path] [output file folder]
|
|
3
|
-
|
|
4
1
|
const fs = require('fs');
|
|
5
2
|
const path = require('path');
|
|
6
3
|
const zlib = require('zlib');
|
|
7
|
-
const
|
|
4
|
+
const { pipeline } = require('stream');
|
|
8
5
|
const utilService = require('./utilService');
|
|
9
6
|
const FranchiseEnum = require('../FranchiseEnum');
|
|
7
|
+
const XmlParser = require('node-xml-stream-parser');
|
|
10
8
|
const EventEmitter = require('events').EventEmitter;
|
|
11
|
-
const extraSchemas = require('../data/schemas/extra-schemas.json');
|
|
12
9
|
|
|
13
10
|
let schemaGenerator = {};
|
|
14
11
|
schemaGenerator.eventEmitter = new EventEmitter();
|
|
@@ -22,103 +19,147 @@ schemaGenerator.generateFromStream = (stream, showOutput, outputFile) => {
|
|
|
22
19
|
schemaGenerator.root = {}
|
|
23
20
|
schemaGenerator.schemas = [];
|
|
24
21
|
schemaGenerator.schemaMap = {};
|
|
22
|
+
schemaGenerator.schemaMeta = {};
|
|
25
23
|
schemaGenerator.enums = [];
|
|
24
|
+
const extraSchemas = schemaGenerator.getExtraSchemas();
|
|
26
25
|
|
|
27
|
-
schemaGenerator.xml = new
|
|
26
|
+
schemaGenerator.xml = new XmlParser();
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
pipeline(
|
|
29
|
+
stream,
|
|
30
|
+
schemaGenerator.xml,
|
|
31
|
+
(err) => {
|
|
32
|
+
if (err) {
|
|
33
|
+
console.error(err);
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
schemaGenerator.enums.forEach((theEnum) => {
|
|
38
|
+
theEnum.setMemberLength();
|
|
39
|
+
});
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const databaseName = data.$.databaseName;
|
|
35
|
-
const gameYear = /Madden(\d{2})/.exec(databaseName)[1];
|
|
41
|
+
const majorVersion = schemaGenerator.schemaMeta.dataMajorVersion;
|
|
42
|
+
const minorVersion = schemaGenerator.schemaMeta.dataMinorVersion;
|
|
43
|
+
const databaseName = schemaGenerator.schemaMeta.databaseName;
|
|
36
44
|
|
|
37
|
-
|
|
38
|
-
calculateInheritedSchemas();
|
|
45
|
+
const gameYear = /Madden(\d{2})/.exec(databaseName)[1];
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
'major': parseInt(majorVersion),
|
|
43
|
-
'minor': parseInt(minorVersion),
|
|
44
|
-
'gameYear': parseInt(gameYear)
|
|
45
|
-
},
|
|
46
|
-
'schemas': schemaGenerator.schemas,
|
|
47
|
-
'schemaMap': schemaGenerator.schemaMap
|
|
48
|
-
};
|
|
47
|
+
addExtraSchemas();
|
|
48
|
+
calculateInheritedSchemas();
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
schemaGenerator.root = {
|
|
51
|
+
'meta': {
|
|
52
|
+
'major': parseInt(majorVersion),
|
|
53
|
+
'minor': parseInt(minorVersion),
|
|
54
|
+
'gameYear': parseInt(gameYear)
|
|
55
|
+
},
|
|
56
|
+
'schemas': schemaGenerator.schemas,
|
|
57
|
+
'schemaMap': schemaGenerator.schemaMap
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
if (outputFile) {
|
|
61
|
+
zlib.gzip(JSON.stringify(schemaGenerator.root), function (_, data) {
|
|
62
|
+
fs.writeFileSync(`${outputFile}\\${majorVersion}_${minorVersion}.gz`, data);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
schemaGenerator.eventEmitter.emit('schemas:done', schemaGenerator.root);
|
|
54
67
|
}
|
|
68
|
+
);
|
|
55
69
|
|
|
56
|
-
|
|
57
|
-
|
|
70
|
+
let currentParent = {
|
|
71
|
+
type: '',
|
|
72
|
+
ref: null
|
|
73
|
+
};
|
|
58
74
|
|
|
59
|
-
schemaGenerator.xml.on('
|
|
60
|
-
if (
|
|
75
|
+
schemaGenerator.xml.on('opentag', (name, attrs) => {
|
|
76
|
+
if (name === 'FranTkData') {
|
|
77
|
+
schemaGenerator.schemaMeta.databaseName = attrs.databaseName;
|
|
78
|
+
schemaGenerator.schemaMeta.dataMajorVersion = attrs.dataMajorVersion;
|
|
79
|
+
schemaGenerator.schemaMeta.dataMinorVersion = attrs.dataMinorVersion;
|
|
80
|
+
}
|
|
61
81
|
|
|
62
|
-
|
|
82
|
+
else if (name === 'enum') {
|
|
83
|
+
let theEnum = parseEnum(attrs);
|
|
84
|
+
schemaGenerator.enums.push(theEnum);
|
|
63
85
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
86
|
+
currentParent = {
|
|
87
|
+
type: 'enum',
|
|
88
|
+
ref: theEnum
|
|
89
|
+
}
|
|
68
90
|
}
|
|
69
91
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
92
|
+
else if (name === 'schema') {
|
|
93
|
+
let schema = parseSchema(attrs);
|
|
94
|
+
schema.attributes = [];
|
|
73
95
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
});
|
|
96
|
+
schemaGenerator.schemas.push(schema);
|
|
97
|
+
schemaGenerator.schemaMap[schema.name] = schema;
|
|
98
|
+
|
|
99
|
+
currentParent = {
|
|
100
|
+
type: 'schema',
|
|
101
|
+
ref: schema
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
else if (name === 'attribute') {
|
|
106
|
+
if (currentParent.type === 'enum') {
|
|
107
|
+
currentParent.ref.addMember(attrs.name, attrs.idx, attrs.value);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const attribute = parseAttribute(attrs);
|
|
111
|
+
currentParent.ref.attributes.push(attribute);
|
|
112
|
+
}
|
|
93
113
|
}
|
|
114
|
+
});
|
|
94
115
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
'
|
|
116
|
+
function parseEnum(enumAttributes) {
|
|
117
|
+
return new FranchiseEnum(enumAttributes.name, enumAttributes.assetId, enumAttributes.isRecordPersistent);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
function parseSchema(schemaAttributes) {
|
|
121
|
+
return {
|
|
122
|
+
'assetId': schemaAttributes.assetId,
|
|
123
|
+
'ownerAssetId': schemaAttributes.ownerAssetId,
|
|
124
|
+
'numMembers': schemaAttributes.numMembers,
|
|
125
|
+
'name': schemaAttributes.name,
|
|
126
|
+
'base': schemaAttributes.base
|
|
102
127
|
};
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
function parseAttribute(attributeAttributes) {
|
|
131
|
+
return {
|
|
132
|
+
'index': attributeAttributes.idx,
|
|
133
|
+
'name': attributeAttributes.name,
|
|
134
|
+
'type': attributeAttributes.type,
|
|
135
|
+
'minValue': attributeAttributes.minValue,
|
|
136
|
+
'maxValue': attributeAttributes.maxValue,
|
|
137
|
+
'maxLength': attributeAttributes.maxLen,
|
|
138
|
+
'default': getDefaultValue(attributeAttributes.default),
|
|
139
|
+
'final': attributeAttributes.final,
|
|
140
|
+
'enum': getEnum(attributeAttributes.type),
|
|
141
|
+
'const': attributeAttributes.const
|
|
142
|
+
}
|
|
103
143
|
|
|
104
|
-
|
|
105
|
-
|
|
144
|
+
function getDefaultValue(defaultVal) {
|
|
145
|
+
if (!defaultVal) { return undefined; }
|
|
106
146
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
147
|
+
defaultVal = defaultVal
|
|
148
|
+
.replace(new RegExp('
', 'g'), '\r')
|
|
149
|
+
.replace(new RegExp('
', 'g'), '\n')
|
|
150
|
+
.replace(new RegExp('&', 'g'), '&')
|
|
151
|
+
.replace(new RegExp('>', 'g'), '>')
|
|
152
|
+
.replace(new RegExp('<', 'g'), '<')
|
|
153
|
+
.replace(new RegExp('"', 'g'), '\"')
|
|
154
|
+
|
|
155
|
+
return defaultVal;
|
|
114
156
|
}
|
|
115
|
-
}
|
|
157
|
+
};
|
|
116
158
|
|
|
117
159
|
function addExtraSchemas() {
|
|
118
160
|
extraSchemas.forEach((schema) => {
|
|
119
|
-
|
|
120
161
|
if (!schemaGenerator.schemaMap[schema.name]) {
|
|
121
|
-
schema.attributes.filter((attrib) => {
|
|
162
|
+
schema.attributes.filter((attrib) => {
|
|
122
163
|
return attrib.enum && !(attrib.enum instanceof FranchiseEnum);
|
|
123
164
|
}).forEach((attrib) => {
|
|
124
165
|
attrib.enum = getEnum(attrib.enum);
|
|
@@ -143,19 +184,7 @@ schemaGenerator.generateFromStream = (stream, showOutput, outputFile) => {
|
|
|
143
184
|
};
|
|
144
185
|
|
|
145
186
|
schemaGenerator.getExtraSchemas = () => {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
extraSchemas.forEach((schema) => {
|
|
149
|
-
schema.attributes.filter((attrib) => {
|
|
150
|
-
return attrib.enum && !(attrib.enum instanceof FranchiseEnum);
|
|
151
|
-
}).forEach((attrib) => {
|
|
152
|
-
attrib.enum = new FranchiseEnum(attrib.enum);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
newSchemas.push(schema);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
return newSchemas;
|
|
187
|
+
return JSON.parse(JSON.stringify(require(path.join(__dirname, '../data/schemas/extra-schemas.json'))));
|
|
159
188
|
};
|
|
160
189
|
|
|
161
190
|
schemaGenerator.calculateInheritedSchemas = (schemaList) => {
|