madden-franchise 2.3.7 → 2.3.8
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/FranchiseFileTable.js +68 -34
- package/package.json +1 -1
package/FranchiseFileTable.js
CHANGED
|
@@ -86,11 +86,7 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
86
86
|
};
|
|
87
87
|
|
|
88
88
|
setNextRecordToUse(index, resetEmptyRecordMap) {
|
|
89
|
-
|
|
90
|
-
this.header.nextRecordToUse = index;
|
|
91
|
-
|
|
92
|
-
// And finally update the buffer to reflect this change
|
|
93
|
-
this.data.writeUInt32BE(index, this.header.headerOffset - 4);
|
|
89
|
+
this._setNextRecordToUseBuffer(index);
|
|
94
90
|
|
|
95
91
|
// Recalculate the empty record map if the option is set and the
|
|
96
92
|
// records have already been read.
|
|
@@ -102,6 +98,63 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
102
98
|
this.emit('change');
|
|
103
99
|
};
|
|
104
100
|
|
|
101
|
+
_setNextRecordToUseBuffer(index) {
|
|
102
|
+
// We need to update the table header to use this row next
|
|
103
|
+
this.header.nextRecordToUse = index;
|
|
104
|
+
|
|
105
|
+
// And finally update the buffer to reflect this change
|
|
106
|
+
this.data.writeUInt32BE(index, this.header.headerOffset - 4);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
recalculateEmptyRecordReferences() {
|
|
110
|
+
// For this method, we are not going to assume any existing empty records.
|
|
111
|
+
// We're going through each record and checking if it is an empty reference.
|
|
112
|
+
// If so, we'll add it to the list. At the end we will check if there are any unreachable empty references
|
|
113
|
+
// and update those accordingly.
|
|
114
|
+
let emptyRecordReferenceIndicies = [];
|
|
115
|
+
|
|
116
|
+
this.records.forEach((record) => {
|
|
117
|
+
let isEmptyReference = false;
|
|
118
|
+
const firstFourBytesReference = utilService.getReferenceData(record._data.slice(0, 32));
|
|
119
|
+
|
|
120
|
+
if (firstFourBytesReference.tableId === 0 && firstFourBytesReference.rowNumber !== 0) {
|
|
121
|
+
// Could be a an empty record reference or a table2 field.
|
|
122
|
+
// Check for a table2 field reference.
|
|
123
|
+
const firstOffset = this.offsetTable[0];
|
|
124
|
+
if (firstOffset.type !== 'string') {
|
|
125
|
+
isEmptyReference = true;
|
|
126
|
+
|
|
127
|
+
// Save the row number that this record points to.
|
|
128
|
+
emptyRecordReferenceIndicies.push(firstFourBytesReference.rowNumber);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
record.isEmpty = isEmptyReference;
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// We need to determine the starting node.
|
|
136
|
+
// To do that, we need to find the empty record which no other empty record points to.
|
|
137
|
+
const unreachableRecords = this.records.filter((record) => { return record.isEmpty; }).filter((record) => {
|
|
138
|
+
return emptyRecordReferenceIndicies.indexOf(record.index) === -1;
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// If there are more than 1 nodes which are not referenced, there is an issue
|
|
142
|
+
if (unreachableRecords.length > 1) {
|
|
143
|
+
const unreachableIndicies = unreachableRecords.map((record) => {
|
|
144
|
+
return record.index;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
console.warn(`(${this.header.tableId}) ${this.name} - More than one unreachable records found: `
|
|
148
|
+
+ `(${unreachableIndicies.join(', ')}). The game will most likely crash if you do not fix this problem. `
|
|
149
|
+
+ `The nextRecordToUse has NOT been updated.`);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
const nextRecordToUse = unreachableRecords[0];
|
|
153
|
+
this._setNextRecordToUseBuffer(nextRecordToUse.index);
|
|
154
|
+
this.emptyRecords = this._parseEmptyRecords();
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
105
158
|
// attribsToLoad is an array of attribute names (strings) to load. It is optional - if nothing is provided to the function it will load all attributes.
|
|
106
159
|
readRecords (attribsToLoad) {
|
|
107
160
|
return new Promise((resolve, reject) => {
|
|
@@ -144,8 +197,7 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
144
197
|
reject('Cannot read records: Schema is not defined.');
|
|
145
198
|
}
|
|
146
199
|
|
|
147
|
-
|
|
148
|
-
|
|
200
|
+
|
|
149
201
|
let offsetTableToUse = this.offsetTable;
|
|
150
202
|
const mandatoryOffsetsToLoad = this.strategy.getMandatoryOffsets(this.offsetTable);
|
|
151
203
|
|
|
@@ -153,18 +205,20 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
153
205
|
// get any new attributes to load plus the existing loaded offsets
|
|
154
206
|
offsetTableToUse = offsetTableToUse.filter((attrib) => {
|
|
155
207
|
return mandatoryOffsetsToLoad.includes(attrib.name)
|
|
156
|
-
|
|
157
|
-
|
|
208
|
+
|| attribsToLoad.includes(attrib.name)
|
|
209
|
+
|| this.loadedOffsets.find((offset) => { return offset.name === attrib.name; });
|
|
158
210
|
});
|
|
159
211
|
}
|
|
160
|
-
|
|
212
|
+
|
|
161
213
|
this.loadedOffsets = offsetTableToUse;
|
|
162
214
|
this.records = readRecords(this.data, this.header, offsetTableToUse);
|
|
163
|
-
|
|
215
|
+
|
|
164
216
|
if (this.header.hasSecondTable) {
|
|
165
217
|
this._parseTable2Values(this.data, this.header, this.records);
|
|
166
218
|
}
|
|
167
219
|
|
|
220
|
+
this.emptyRecords = this._parseEmptyRecords();
|
|
221
|
+
|
|
168
222
|
this.records.forEach((record, index) => {
|
|
169
223
|
if (this.isArray) {
|
|
170
224
|
record.arraySize = this.arraySizes[index];
|
|
@@ -249,27 +303,6 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
249
303
|
}
|
|
250
304
|
}
|
|
251
305
|
}
|
|
252
|
-
else {
|
|
253
|
-
// The field was not empty, let's check if it is now
|
|
254
|
-
const referenceData = utilService.getReferenceData(this._data.slice(0, 32));
|
|
255
|
-
if (referenceData.tableId === 0) {
|
|
256
|
-
// The record has a reference to table id 0, now we need to see if its referencing the 0th record or not
|
|
257
|
-
// We have to be careful not to mistake a null reference for an empty reference to record 0
|
|
258
|
-
if (referenceData.rowNumber !== 0) {
|
|
259
|
-
// If the value is referencing a row number greater than 0, we need to treat this record as an empty reference.
|
|
260
|
-
// onRecordEmpty(record);
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
// The record was updated to either be a null reference or an empty record reference to row 0.
|
|
264
|
-
// First let's make sure we aren't editing row 0...if we are, then the value is a null reference
|
|
265
|
-
// because a record cannot point to itself.
|
|
266
|
-
if (this.index > 0) {
|
|
267
|
-
// Now that we know that the edit isn't coming from row 0, let's check if row 0 is an empty reference.
|
|
268
|
-
// If it is NOT an empty reference, then the updated value is not an empty reference.
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
306
|
}
|
|
274
307
|
|
|
275
308
|
that.emit('change');
|
|
@@ -379,9 +412,10 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
379
412
|
let previousEmptyRecordIndex = null;
|
|
380
413
|
let currentEmptyRecordIndex = firstEmptyRecord;
|
|
381
414
|
|
|
382
|
-
if (
|
|
415
|
+
if (firstEmptyRecord !== this.header.recordCapacity) {
|
|
383
416
|
while (currentEmptyRecordIndex !== this.header.recordCapacity) {
|
|
384
|
-
let nextEmptyRecordIndex = this.data.readUInt32BE(this.header.table1StartIndex + (currentEmptyRecordIndex * sizeOfEachRecord));
|
|
417
|
+
// let nextEmptyRecordIndex = this.data.readUInt32BE(this.header.table1StartIndex + (currentEmptyRecordIndex * sizeOfEachRecord));
|
|
418
|
+
let nextEmptyRecordIndex = utilService.getReferenceData(this.records[currentEmptyRecordIndex]._data.slice(0, 32)).rowNumber;
|
|
385
419
|
|
|
386
420
|
emptyRecords.set(currentEmptyRecordIndex, {
|
|
387
421
|
previous: previousEmptyRecordIndex,
|