madden-franchise 2.3.15 → 2.5.0

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 CHANGED
@@ -286,6 +286,41 @@ class FranchiseFile extends EventEmitter {
286
286
  return null;
287
287
  }
288
288
  };
289
+
290
+ getReferencesToRecord(tableId, recordIndex) {
291
+ const referencedTable = this.getTableById(tableId);
292
+
293
+ if (referencedTable) {
294
+ const fullBinary = utilService.getBinaryReferenceData(tableId, recordIndex);
295
+ const hex = utilService.bin2hex(fullBinary).padStart(8, '0');
296
+
297
+ return this.tables.filter((table) => {
298
+ if (table.schema) {
299
+ return table.schema && table.schema.attributes.find((attribute) => {
300
+ return attribute.type === referencedTable.name;
301
+ });
302
+ }
303
+ else if (table.isArray && referencedTable.schema) {
304
+ // If the referenced table has a schema, we can check its base name.
305
+ // Some array table names are by the base name like EnumTable[] can contain AwardTypeEnumTableEntry
306
+
307
+ return table.name.slice(0, table.name.length - 2) === referencedTable.name
308
+ || table.name.slice(0, table.name.length - 2) === referencedTable.schema.base;
309
+ }
310
+ else if (table.isArray) {
311
+ return table.name.slice(0, table.name.length - 2) === referencedTable.name;
312
+ }
313
+ }).filter((table) => {
314
+ return table.data.indexOf(hex, 0, 'hex') !== -1;
315
+ }).map((table) => {
316
+ return {
317
+ tableId: table.header.tableId,
318
+ name: table.name,
319
+ table: table
320
+ }
321
+ });
322
+ }
323
+ };
289
324
  };
290
325
 
291
326
  module.exports = FranchiseFile;
@@ -44,6 +44,10 @@ class FranchiseFileTable extends EventEmitter {
44
44
  get schema () {
45
45
  return this._schema;
46
46
  };
47
+
48
+ getBinaryReferenceToRecord(index) {
49
+ return utilService.getBinaryReferenceData(this.header.tableId, index);
50
+ };
47
51
 
48
52
  updateBuffer() {
49
53
  // need to check table2 data first because it may change offsets of the legit records.
@@ -592,7 +596,7 @@ function readOffsetTable(data, schema, header) {
592
596
  'originalIndex': parseInt(attribute.index),
593
597
  'name': attribute.name,
594
598
  'type': (minValue < 0 || maxValue < 0) ? 's_' + attribute.type : attribute.type,
595
- 'isReference': !attribute.enum && (attribute.type[0] == attribute.type[0].toUpperCase() || attribute.type.includes('[]')) ? true : false,
599
+ 'isReference': !attribute.enum && (attribute.type[0] == attribute.type[0].toUpperCase() || attribute.type.includes('[]') || attribute.type === 'record') ? true : false,
596
600
  'valueInSecondTable': header.hasSecondTable && attribute.type === 'string',
597
601
  'isSigned': minValue < 0 || maxValue < 0,
598
602
  'minValue': minValue,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "madden-franchise",
3
- "version": "2.3.15",
3
+ "version": "2.5.0",
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.4.5"
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": "^6.2.2",
25
+ "mocha": "^9.1.4",
26
26
  "proxyquire": "^2.1.3",
27
27
  "sinon": "^7.5.0"
28
28
  }
@@ -1,14 +1,12 @@
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 XmlStream = require('xml-stream');
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');
9
+ const extraSchemas = JSON.parse(JSON.stringify(require(path.join(__dirname, '../data/schemas/extra-schemas.json'))));
12
10
 
13
11
  let schemaGenerator = {};
14
12
  schemaGenerator.eventEmitter = new EventEmitter();
@@ -22,101 +20,144 @@ schemaGenerator.generateFromStream = (stream, showOutput, outputFile) => {
22
20
  schemaGenerator.root = {}
23
21
  schemaGenerator.schemas = [];
24
22
  schemaGenerator.schemaMap = {};
23
+ schemaGenerator.schemaMeta = {};
25
24
  schemaGenerator.enums = [];
26
25
 
27
- schemaGenerator.xml = new XmlStream(stream);
26
+ schemaGenerator.xml = new XmlParser();
28
27
 
29
- schemaGenerator.xml.collect('attribute');
28
+ pipeline(
29
+ stream,
30
+ schemaGenerator.xml,
31
+ (err) => {
32
+ if (err) {
33
+ console.error(err);
34
+ throw err;
35
+ }
30
36
 
31
- schemaGenerator.xml.on('endElement: FranTkData', function (data) {
32
- const majorVersion = data.$.dataMajorVersion;
33
- const minorVersion = data.$.dataMinorVersion;
34
- const databaseName = data.$.databaseName;
35
- const gameYear = /Madden(\d{2})/.exec(databaseName)[1];
37
+ schemaGenerator.enums.forEach((theEnum) => {
38
+ theEnum.setMemberLength();
39
+ });
36
40
 
37
- addExtraSchemas();
38
- calculateInheritedSchemas();
41
+ const majorVersion = schemaGenerator.schemaMeta.dataMajorVersion;
42
+ const minorVersion = schemaGenerator.schemaMeta.dataMinorVersion;
43
+ const databaseName = schemaGenerator.schemaMeta.databaseName;
39
44
 
40
- schemaGenerator.root = {
41
- 'meta': {
42
- 'major': parseInt(majorVersion),
43
- 'minor': parseInt(minorVersion),
44
- 'gameYear': parseInt(gameYear)
45
- },
46
- 'schemas': schemaGenerator.schemas,
47
- 'schemaMap': schemaGenerator.schemaMap
48
- };
45
+ const gameYear = /Madden(\d{2})/.exec(databaseName)[1];
49
46
 
50
- if (outputFile) {
51
- zlib.gzip(JSON.stringify(schemaGenerator.root), function (_, data) {
52
- fs.writeFileSync(`${outputFile}\\${majorVersion}_${minorVersion}.gz`, data);
53
- });
47
+ addExtraSchemas();
48
+ calculateInheritedSchemas();
49
+
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
- schemaGenerator.eventEmitter.emit('schemas:done', schemaGenerator.root);
57
- });
70
+ let currentParent = {
71
+ type: '',
72
+ ref: null
73
+ };
58
74
 
59
- schemaGenerator.xml.on('endElement: enum', function (theEnum) {
60
- if (showOutput) console.log(`Adding enum ${theEnum.$.name}`);
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
- let newEnum = new FranchiseEnum(theEnum.$.name, theEnum.$.assetId, theEnum.$.isRecordPersistent);
82
+ else if (name === 'enum') {
83
+ let theEnum = parseEnum(attrs);
84
+ schemaGenerator.enums.push(theEnum);
63
85
 
64
- if (theEnum.attribute) {
65
- theEnum.attribute.forEach((attribute) => {
66
- newEnum.addMember(attribute.$.name, attribute.$.idx, attribute.$.value);
67
- });
86
+ currentParent = {
87
+ type: 'enum',
88
+ ref: theEnum
89
+ }
68
90
  }
69
91
 
70
- newEnum.setMemberLength();
71
- schemaGenerator.enums.push(newEnum);
72
- });
92
+ else if (name === 'schema') {
93
+ let schema = parseSchema(attrs);
94
+ schema.attributes = [];
73
95
 
74
- schemaGenerator.xml.on('endElement: schema', function (schema) {
75
- if (showOutput) console.log(`Adding schema ${schema.$.name}`);
76
- let attributes = [];
77
-
78
- if (schema.attribute) {
79
- attributes = schema.attribute.map((attribute) => {
80
- return {
81
- 'index': attribute.$.idx,
82
- 'name': attribute.$.name,
83
- 'type': attribute.$.type,
84
- 'minValue': attribute.$.minValue,
85
- 'maxValue': attribute.$.maxValue,
86
- 'maxLength': attribute.$.maxLen,
87
- 'default': attribute.$.default,
88
- 'final': attribute.$.final,
89
- 'enum': getEnum(attribute.$.type),
90
- 'const': attribute.$.const
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
+ });
115
+
116
+ function parseEnum(enumAttributes) {
117
+ return new FranchiseEnum(enumAttributes.name, enumAttributes.assetId, enumAttributes.isRecordPersistent);
118
+ };
94
119
 
95
- const element = {
96
- 'assetId': schema.$.assetId,
97
- 'ownerAssetId': schema.$.ownerAssetId,
98
- 'numMembers': schema.$.numMembers,
99
- 'name': schema.$.name,
100
- 'base': schema.$.base,
101
- 'attributes': attributes
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
- schemaGenerator.schemas.push(element);
105
- schemaGenerator.schemaMap[element.name] = element;
144
+ function getDefaultValue(defaultVal) {
145
+ if (!defaultVal) { return undefined; }
106
146
 
107
- if (element.name === 'WinLossStreakPlayerGoal') {
108
- // calculateInheritedSchemas();
109
- // // fs.writeFileSync(outputFile, JSON.stringify(schemaGenerator.schemas));
110
- // zlib.gzip(JSON.stringify(schemaGenerator.schemas), function (_, data) {
111
- // fs.writeFileSync(outputFile, data);
112
- // });
113
- // schemaGenerator.emit('schemas:done', schemaGenerator.schemas);
147
+ defaultVal = defaultVal
148
+ .replace(new RegExp('&#xD;', 'g'), '\r')
149
+ .replace(new RegExp('&#xA;', 'g'), '\n')
150
+ .replace(new RegExp('&amp;', 'g'), '&')
151
+ .replace(new RegExp('&gt;', 'g'), '>')
152
+ .replace(new RegExp('&lt;', 'g'), '<')
153
+ .replace(new RegExp('&quot;', '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
162
  schema.attributes.filter((attrib) => {
122
163
  return attrib.enum && !(attrib.enum instanceof FranchiseEnum);