madden-franchise 2.3.3 → 2.3.7
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/FranchiseFileField.js
CHANGED
|
@@ -68,7 +68,7 @@ class FranchiseFileField extends EventEmitter {
|
|
|
68
68
|
this.emit('change');
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
-
setUnformattedValueWithoutChangeEvent(unformattedValue) {
|
|
71
|
+
setUnformattedValueWithoutChangeEvent(unformattedValue, suppressErrors) {
|
|
72
72
|
if (!utilService.isString(unformattedValue)) { throw new Error(`Argument must be of type string. You passed in a ${typeof unformattedValue}.`); }
|
|
73
73
|
else if (!utilService.stringOnlyContainsBinaryDigits(unformattedValue)) { throw new Error(`Argument must only contain binary digits 1 and 0. If you would like to set the value, please set the 'value' attribute instead.`)}
|
|
74
74
|
else {
|
|
@@ -82,7 +82,7 @@ class FranchiseFileField extends EventEmitter {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
// check for 'allowed' error - this will be true if the unformatted value is invalid.
|
|
85
|
-
if (this._offset.enum && value === unformattedValue.padStart(this._offset.length, '0')) {
|
|
85
|
+
if (this._offset.enum && value === unformattedValue.padStart(this._offset.length, '0') && !suppressErrors) {
|
|
86
86
|
throw new Error(`Argument is not a valid unformatted value for this field. You passed in ${value}.`)
|
|
87
87
|
}
|
|
88
88
|
|
package/FranchiseFileTable.js
CHANGED
|
@@ -25,6 +25,27 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
get hexData () {
|
|
28
|
+
this.updateBuffer();
|
|
29
|
+
return this.data;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
set schema (schema) {
|
|
33
|
+
// console.time('set schema');
|
|
34
|
+
this._schema = schema;
|
|
35
|
+
const modifiedHeaderAttributes = this.strategy.parseHeaderAttributesFromSchema(schema, this.data, this.header);
|
|
36
|
+
|
|
37
|
+
this.header.headerSize = modifiedHeaderAttributes.headerSize;
|
|
38
|
+
this.header.record1Size = modifiedHeaderAttributes.record1Size;
|
|
39
|
+
this.header.table1StartIndex = modifiedHeaderAttributes.table1StartIndex;
|
|
40
|
+
this.header.table2StartIndex = modifiedHeaderAttributes.table2StartIndex;
|
|
41
|
+
// console.timeEnd('set schema');
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
get schema () {
|
|
45
|
+
return this._schema;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
updateBuffer() {
|
|
28
49
|
// need to check table2 data first because it may change offsets of the legit records.
|
|
29
50
|
const table2Data = this.strategy.getTable2BinaryData(this.table2Records, this.data.slice(this.header.table2StartIndex));
|
|
30
51
|
|
|
@@ -62,23 +83,23 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
62
83
|
bufferArrays = bufferArrays.concat(table2Data);
|
|
63
84
|
|
|
64
85
|
this.data = Buffer.concat(bufferArrays);
|
|
65
|
-
return this.data;
|
|
66
86
|
};
|
|
67
87
|
|
|
68
|
-
|
|
69
|
-
//
|
|
70
|
-
this.
|
|
71
|
-
const modifiedHeaderAttributes = this.strategy.parseHeaderAttributesFromSchema(schema, this.data, this.header);
|
|
88
|
+
setNextRecordToUse(index, resetEmptyRecordMap) {
|
|
89
|
+
// We need to update the table header to use this row next
|
|
90
|
+
this.header.nextRecordToUse = index;
|
|
72
91
|
|
|
73
|
-
this
|
|
74
|
-
this.header.
|
|
75
|
-
this.header.table1StartIndex = modifiedHeaderAttributes.table1StartIndex;
|
|
76
|
-
this.header.table2StartIndex = modifiedHeaderAttributes.table2StartIndex;
|
|
77
|
-
// console.timeEnd('set schema');
|
|
78
|
-
};
|
|
92
|
+
// And finally update the buffer to reflect this change
|
|
93
|
+
this.data.writeUInt32BE(index, this.header.headerOffset - 4);
|
|
79
94
|
|
|
80
|
-
|
|
81
|
-
|
|
95
|
+
// Recalculate the empty record map if the option is set and the
|
|
96
|
+
// records have already been read.
|
|
97
|
+
if (resetEmptyRecordMap && this.recordsRead) {
|
|
98
|
+
this.updateBuffer();
|
|
99
|
+
this.emptyRecords = this._parseEmptyRecords();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.emit('change');
|
|
82
103
|
};
|
|
83
104
|
|
|
84
105
|
// 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.
|
|
@@ -154,6 +175,7 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
154
175
|
}
|
|
155
176
|
|
|
156
177
|
const that = this;
|
|
178
|
+
|
|
157
179
|
record.on('change', function (changedOffset) {
|
|
158
180
|
this.isChanged = true;
|
|
159
181
|
|
|
@@ -215,7 +237,7 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
215
237
|
if (!previousEmptyReference) {
|
|
216
238
|
// If no previous empty record exists and a next record exists, we need to update the header to
|
|
217
239
|
// point to this record as the next record to use.
|
|
218
|
-
|
|
240
|
+
that.setNextRecordToUse(emptyRecordReference.next);
|
|
219
241
|
}
|
|
220
242
|
}
|
|
221
243
|
|
|
@@ -223,7 +245,28 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
223
245
|
// Then there are no more empty references in the table
|
|
224
246
|
// Update the table header nextRecordToUse back to the table record capacity
|
|
225
247
|
if (!previousEmptyReference && !nextEmptyReference) {
|
|
226
|
-
|
|
248
|
+
that.setNextRecordToUse(that.header.recordCapacity);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
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
|
+
}
|
|
227
270
|
}
|
|
228
271
|
}
|
|
229
272
|
}
|
|
@@ -233,10 +276,14 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
233
276
|
});
|
|
234
277
|
|
|
235
278
|
record.on('empty', function () {
|
|
279
|
+
onRecordEmpty(this);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
function onRecordEmpty(record) {
|
|
236
283
|
// First, check if the record is already empty. If so, don't do anything...
|
|
237
284
|
// If not empty, then we need to empty it.
|
|
238
|
-
if (!
|
|
239
|
-
|
|
285
|
+
if (!record.isEmpty) {
|
|
286
|
+
record.isChanged = true;
|
|
240
287
|
const lastEmptyRecordMapEntry = Array.from(that.emptyRecords).pop();
|
|
241
288
|
|
|
242
289
|
// When we empty a record, we need to check if another empty record exists in the table.
|
|
@@ -248,11 +295,11 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
248
295
|
|
|
249
296
|
that.emptyRecords.set(lastEmptyRecordIndex, {
|
|
250
297
|
previous: lastEmptyRecordMapEntry[1].previous,
|
|
251
|
-
next:
|
|
298
|
+
next: record.index
|
|
252
299
|
});
|
|
253
300
|
|
|
254
301
|
// Then we need to update the current record index to point to the record capacity.
|
|
255
|
-
that.emptyRecords.set(
|
|
302
|
+
that.emptyRecords.set(record.index, {
|
|
256
303
|
previous: lastEmptyRecordIndex,
|
|
257
304
|
next: that.header.recordCapacity
|
|
258
305
|
});
|
|
@@ -263,32 +310,24 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
263
310
|
|
|
264
311
|
// And update both record's data. This will set the unformatted and formatted values
|
|
265
312
|
// without emitting an event
|
|
266
|
-
changeRecordBuffers(lastEmptyRecordIndex,
|
|
267
|
-
changeRecordBuffers(
|
|
313
|
+
changeRecordBuffers(lastEmptyRecordIndex, record.index);
|
|
314
|
+
changeRecordBuffers(record.index, that.header.recordCapacity);
|
|
268
315
|
}
|
|
269
316
|
else {
|
|
270
317
|
// In this case, the record that was emptied is the first empty record in the table
|
|
271
|
-
that.emptyRecords.set(
|
|
318
|
+
that.emptyRecords.set(record.index, {
|
|
272
319
|
previous: null,
|
|
273
320
|
next: that.header.recordCapacity
|
|
274
321
|
});
|
|
275
322
|
|
|
276
323
|
// Finally update the table header and buffer so that the game uses this new empty
|
|
277
324
|
// record as the next record to use (or fill)
|
|
278
|
-
|
|
279
|
-
changeRecordBuffers(
|
|
325
|
+
that.setNextRecordToUse(record.index);
|
|
326
|
+
changeRecordBuffers(record.index, that.header.recordCapacity);
|
|
280
327
|
}
|
|
281
328
|
|
|
282
329
|
that.emit('change');
|
|
283
330
|
}
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
function updateNextRecordToUseHeaderAndBuffer(nextRecordToUse) {
|
|
287
|
-
// We need to update the table header to use this row next
|
|
288
|
-
that.header.nextRecordToUse = nextRecordToUse;
|
|
289
|
-
|
|
290
|
-
// And finally update the buffer to reflect this change
|
|
291
|
-
that.data.writeUInt32BE(nextRecordToUse, that.header.headerOffset - 4);
|
|
292
331
|
};
|
|
293
332
|
|
|
294
333
|
function changeRecordBuffers(index, emptyRecordReference) {
|
|
@@ -299,7 +338,7 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
299
338
|
function setBufferToEmptyRecordReference(index, emptyRecordReference) {
|
|
300
339
|
const recordStartIndex = that.header.table1StartIndex + (index * that.header.record1Size)
|
|
301
340
|
that.data.writeUInt32BE(emptyRecordReference, recordStartIndex);
|
|
302
|
-
that.data.fill(0, recordStartIndex + 4, recordStartIndex + that.header.record1Size);
|
|
341
|
+
// that.data.fill(0, recordStartIndex + 4, recordStartIndex + that.header.record1Size);
|
|
303
342
|
};
|
|
304
343
|
|
|
305
344
|
function setRecordInternalBuffer(index, emptyRecordReference) {
|
|
@@ -307,7 +346,7 @@ class FranchiseFileTable extends EventEmitter {
|
|
|
307
346
|
|
|
308
347
|
const recordSizeInBits = that.header.record1Size * 8;
|
|
309
348
|
if (recordSizeInBits > 32) {
|
|
310
|
-
newData +=
|
|
349
|
+
newData += that.records[index]._data.slice(32);
|
|
311
350
|
}
|
|
312
351
|
|
|
313
352
|
that.records[index].data = newData;
|
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++) {
|