madden-franchise 2.3.4 → 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
CHANGED
|
@@ -86,16 +86,71 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
86
86
|
};
|
|
87
87
|
|
|
88
88
|
setNextRecordToUse(index, resetEmptyRecordMap) {
|
|
89
|
+
this._setNextRecordToUseBuffer(index);
|
|
90
|
+
|
|
91
|
+
// Recalculate the empty record map if the option is set and the
|
|
92
|
+
// records have already been read.
|
|
93
|
+
if (resetEmptyRecordMap && this.recordsRead) {
|
|
94
|
+
this.updateBuffer();
|
|
95
|
+
this.emptyRecords = this._parseEmptyRecords();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.emit('change');
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
_setNextRecordToUseBuffer(index) {
|
|
89
102
|
// We need to update the table header to use this row next
|
|
90
103
|
this.header.nextRecordToUse = index;
|
|
91
104
|
|
|
92
105
|
// And finally update the buffer to reflect this change
|
|
93
106
|
this.data.writeUInt32BE(index, this.header.headerOffset - 4);
|
|
107
|
+
};
|
|
94
108
|
|
|
95
|
-
|
|
96
|
-
//
|
|
97
|
-
if
|
|
98
|
-
|
|
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);
|
|
99
154
|
this.emptyRecords = this._parseEmptyRecords();
|
|
100
155
|
}
|
|
101
156
|
};
|
|
@@ -142,8 +197,7 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
142
197
|
reject('Cannot read records: Schema is not defined.');
|
|
143
198
|
}
|
|
144
199
|
|
|
145
|
-
|
|
146
|
-
|
|
200
|
+
|
|
147
201
|
let offsetTableToUse = this.offsetTable;
|
|
148
202
|
const mandatoryOffsetsToLoad = this.strategy.getMandatoryOffsets(this.offsetTable);
|
|
149
203
|
|
|
@@ -151,18 +205,20 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
151
205
|
// get any new attributes to load plus the existing loaded offsets
|
|
152
206
|
offsetTableToUse = offsetTableToUse.filter((attrib) => {
|
|
153
207
|
return mandatoryOffsetsToLoad.includes(attrib.name)
|
|
154
|
-
|
|
155
|
-
|
|
208
|
+
|| attribsToLoad.includes(attrib.name)
|
|
209
|
+
|| this.loadedOffsets.find((offset) => { return offset.name === attrib.name; });
|
|
156
210
|
});
|
|
157
211
|
}
|
|
158
|
-
|
|
212
|
+
|
|
159
213
|
this.loadedOffsets = offsetTableToUse;
|
|
160
214
|
this.records = readRecords(this.data, this.header, offsetTableToUse);
|
|
161
|
-
|
|
215
|
+
|
|
162
216
|
if (this.header.hasSecondTable) {
|
|
163
217
|
this._parseTable2Values(this.data, this.header, this.records);
|
|
164
218
|
}
|
|
165
219
|
|
|
220
|
+
this.emptyRecords = this._parseEmptyRecords();
|
|
221
|
+
|
|
166
222
|
this.records.forEach((record, index) => {
|
|
167
223
|
if (this.isArray) {
|
|
168
224
|
record.arraySize = this.arraySizes[index];
|
|
@@ -247,14 +303,6 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
247
303
|
}
|
|
248
304
|
}
|
|
249
305
|
}
|
|
250
|
-
else {
|
|
251
|
-
// The field was not empty, let's check if it is now
|
|
252
|
-
const referenceData = utilService.getReferenceData(this._data.slice(0, 32));
|
|
253
|
-
if (referenceData.tableId === 0) {
|
|
254
|
-
// In this case, the record is now empty. Add an entry to the empty record map
|
|
255
|
-
// onRecordEmpty(this);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
306
|
}
|
|
259
307
|
|
|
260
308
|
that.emit('change');
|
|
@@ -323,7 +371,7 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
323
371
|
function setBufferToEmptyRecordReference(index, emptyRecordReference) {
|
|
324
372
|
const recordStartIndex = that.header.table1StartIndex + (index * that.header.record1Size)
|
|
325
373
|
that.data.writeUInt32BE(emptyRecordReference, recordStartIndex);
|
|
326
|
-
that.data.fill(0, recordStartIndex + 4, recordStartIndex + that.header.record1Size);
|
|
374
|
+
// that.data.fill(0, recordStartIndex + 4, recordStartIndex + that.header.record1Size);
|
|
327
375
|
};
|
|
328
376
|
|
|
329
377
|
function setRecordInternalBuffer(index, emptyRecordReference) {
|
|
@@ -331,7 +379,7 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
331
379
|
|
|
332
380
|
const recordSizeInBits = that.header.record1Size * 8;
|
|
333
381
|
if (recordSizeInBits > 32) {
|
|
334
|
-
newData +=
|
|
382
|
+
newData += that.records[index]._data.slice(32);
|
|
335
383
|
}
|
|
336
384
|
|
|
337
385
|
that.records[index].data = newData;
|
|
@@ -364,9 +412,10 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
364
412
|
let previousEmptyRecordIndex = null;
|
|
365
413
|
let currentEmptyRecordIndex = firstEmptyRecord;
|
|
366
414
|
|
|
367
|
-
if (
|
|
415
|
+
if (firstEmptyRecord !== this.header.recordCapacity) {
|
|
368
416
|
while (currentEmptyRecordIndex !== this.header.recordCapacity) {
|
|
369
|
-
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;
|
|
370
419
|
|
|
371
420
|
emptyRecords.set(currentEmptyRecordIndex, {
|
|
372
421
|
previous: previousEmptyRecordIndex,
|
package/package.json
CHANGED
package/scripts/deflate.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const zlib = require('zlib');
|
|
3
3
|
|
|
4
|
-
const filePath = 'D:\\Projects\\Madden 22\\Expressions\\
|
|
4
|
+
const filePath = 'D:\\Projects\\Madden 22\\Expressions\\sabo-expression-binary.frt';
|
|
5
5
|
const outputPath = 'D:\\Projects\\Madden 22\\Expressions\\modified-Franchise-Expression-binary.FTC'
|
|
6
6
|
|
|
7
7
|
const stream = fs.createReadStream(filePath)
|
|
@@ -13,6 +13,9 @@ CommonAlgorithms.save = (units, oldData) => {
|
|
|
13
13
|
let oldOffsetCounter = 0;
|
|
14
14
|
let bufferArrays = [];
|
|
15
15
|
|
|
16
|
+
// Ensure the units are sorted by index in the actual file. Otherwise, we may overwrite data
|
|
17
|
+
units.sort((a, b) => { return a.index - b.index; });
|
|
18
|
+
|
|
16
19
|
units.forEach((unit, index) => {
|
|
17
20
|
if (unit.offset === 0 && index > 0) {
|
|
18
21
|
// there are usually trailing records at the end of the table that reference
|
|
@@ -3,7 +3,8 @@ let FranchiseTableStrategy = {};
|
|
|
3
3
|
FranchiseTableStrategy.getTable2BinaryData = (table2Records, fullTable2Buffer) => {
|
|
4
4
|
let table2Data = [];
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// Make sure to sort the table2 records by index
|
|
7
|
+
const changedTable2Records = table2Records.filter((record) => { return record.isChanged; }).sort((a, b) => { return a.index - b.index; });
|
|
7
8
|
let currentOffset = 0;
|
|
8
9
|
|
|
9
10
|
for (let i = 0; i < changedTable2Records.length; i++) {
|