This commit is contained in:
Alessandro Autiero
2025-03-23 20:26:13 +01:00
parent 9a000db3b7
commit 5d8f6bf0fa
16 changed files with 205 additions and 117 deletions

View File

@@ -6,6 +6,7 @@ import 'dart:typed_data';
import 'package:ffi/ffi.dart';
import 'package:reboot_common/common.dart';
import 'package:win32/win32.dart';
import 'package:path/path.dart' as path;
final DynamicLibrary _shell32 = DynamicLibrary.open('shell32.dll');
final SHGetPropertyStoreFromParsingName =
@@ -32,6 +33,122 @@ final Uint8List _patchedMatchmaking = Uint8List.fromList([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
]);
// https://github.com/polynite/fn-releases
const Map<int, String> _buildToGameVersion = {
2870186: "1.0.0",
3700114: "1.7.2",
3724489: "1.8.0",
3729133: "1.8.1",
3741772: "1.8.2",
3757339: "1.9",
3775276: "1.9.1",
3790078: "1.10",
3807424: "1.11",
3825894: "2.1",
3841827: "2.2",
3847564: "2.3",
3858292: "2.4",
3870737: "2.4.2",
3889387: "2.5",
3901517: "3.0.0",
3915963: "3.1",
3917250: "3.1.1",
3935073: "3.2",
3942182: "3.3",
4008490: "3.5",
4019403: "3.6",
4039451: "4.0",
4053532: "4.1",
4072250: "4.2",
4117433: "4.4",
4127312: "4.4.1",
4159770: "4.5",
4204761: "5.0",
4214610: "5.01",
4240749: "5.10",
4288479: "5.21",
4305896: "5.30",
4352937: "5.40",
4363240: "5.41",
4395664: "6.0",
4424678: "6.01",
4461277: "6.0.2",
4464155: "6.10",
4476098: "6.10.1",
4480234: "6.10.2",
4526925: "6.21",
4543176: "6.22",
4573279: "6.31",
4629139: "7.0",
4667333: "7.10",
4727874: "7.20",
4834550: "7.30",
5046157: "7.40",
5203069: "8.00",
5625478: "8.20",
5793395: "8.30",
6005771: "8.40",
6058028: "8.50",
6165369: "8.51",
6337466: "9.00",
6428087: "9.01",
6639283: "9.10",
6922310: "9.21",
7095426: "9.30",
7315705: "9.40",
7609292: "9.41",
7704164: "10.00",
7955722: "10.10",
8456527: "10.20",
8723043: "10.31",
9380822: "10.40",
9603448: "11.00",
9901083: "11.10",
10708866: "11.30",
10800459: "11.31",
11265652: "11.50",
11556442: "12.00",
11883027: "12.10",
12353830: "12.21",
12905909: "12.41",
13137020: "12.50",
13498980: "12.61",
14113327: "13.40",
14211474: "14.00",
14456520: "14.30",
14550713: "14.40",
14786821: "14.60",
14835335: "15.00",
15014719: "15.10",
15341163: "15.30",
15526472: "15.50",
15913292: "16.10",
16163563: "16.30",
16218553: "16.40",
16469788: "16.50",
16745144: "17.10",
17004569: "17.30",
17269705: "17.40",
17388565: "17.50",
17468642: "18.00",
17661844: "18.10",
17745267: "18.20",
17811397: "18.21",
17882303: "18.30",
18163738: "18.40",
18489740: "19.01",
18675304: "19.10",
19458861: "20.00",
19598943: "20.10",
19751212: "20.20",
19950687: "20.30",
20244966: "20.40",
20463113: "21.00",
20696680: "21.10",
21035704: "21.20",
21657658: "21.50",
};
Future<bool> patchHeadless(File file) async =>
await _patch(file, _originalHeadless, _patchedHeadless);
@@ -179,8 +296,23 @@ String _parseUsername(String username, bool host) {
return username;
}
Future<String> extractGameVersion(String filePath, String defaultGameVersion) => Isolate.run(() {
final filePathPtr = filePath.toNativeUtf16();
// Parsing the version is not that easy
// Also on some versions the shipping exe has it as well, but not on all: that's why i'm using the crash report client
// ++Fortnite+Release-34.10-CL-40567068
// 4.16.0-3700114+++Fortnite+Release-Cert
// 4.19.0-3870737+++Fortnite+Release-Next
// 4.20.0-4008490+++Fortnite+Release-3.5
Future<String> extractGameVersion(Directory directory) => Isolate.run(() async {
log("[VERSION] Looking for $kCrashReportExe in ${directory.path}");
final defaultGameVersion = path.basename(directory.path);
final crashReportClients = await findFiles(directory, kCrashReportExe);
if (crashReportClients.isEmpty) {
log("[VERSION] Didn't find a unique match: $crashReportClients");
return defaultGameVersion;
}
log("[VERSION] Extracting game version from ${crashReportClients.last.path}(default: $defaultGameVersion)");
final filePathPtr = crashReportClients.last.path.toNativeUtf16();
final pPropertyStore = calloc<COMObject>();
final iidPropertyStore = GUIDFromString(IID_IPropertyStore);
final ret = SHGetPropertyStoreFromParsingName(
@@ -195,8 +327,9 @@ Future<String> extractGameVersion(String filePath, String defaultGameVersion) =>
calloc.free(iidPropertyStore);
if (FAILED(ret)) {
log("[VERSION] Using default value");
calloc.free(pPropertyStore);
throw WindowsException(ret);
return defaultGameVersion;
}
final propertyStore = IPropertyStore(pPropertyStore);
@@ -206,7 +339,8 @@ Future<String> extractGameVersion(String filePath, String defaultGameVersion) =>
final count = countPtr.value;
calloc.free(countPtr);
if (FAILED(hrCount)) {
throw WindowsException(hrCount);
log("[VERSION] Using default value");
return defaultGameVersion;
}
for (var i = 0; i < count; i++) {
@@ -222,48 +356,20 @@ Future<String> extractGameVersion(String filePath, String defaultGameVersion) =>
if (!FAILED(hrValue)) {
if (pv.ref.vt == VARENUM.VT_LPWSTR) {
final valueStr = pv.ref.pwszVal.toDartString();
if (valueStr.contains("+++Fortnite")) {
var gameVersion = valueStr.substring(valueStr.lastIndexOf("-") + 1);
if(gameVersion == "Cert") {
final headerIndex = valueStr.indexOf("++Fortnite");
if (headerIndex != -1) {
log("[VERSION] Found value string: $valueStr");
var gameVersion = valueStr.substring(valueStr.indexOf("-", headerIndex) + 1);
log("[VERSION] Game version: $gameVersion");
if(gameVersion == "Cert" || gameVersion == "Next") {
final engineVersion = valueStr.substring(0, valueStr.indexOf("+"));
log("[VERSION] Engine version: $engineVersion");
final engineVersionParts = engineVersion.split("-");
final engineVersionBuild = int.parse(engineVersionParts[1]);
switch (engineVersionBuild) {
case 2870186:
gameVersion = "OT6.5";
break;
case 3700114:
gameVersion = "1.7.2";
break;
case 3724489:
gameVersion = "1.8.0";
break;
case 3729133:
gameVersion = "1.8.1";
break;
case 3741772:
gameVersion = "1.8.2";
break;
case 3757339:
gameVersion = "1.9";
break;
case 3775276:
gameVersion = "1.9.1";
break;
case 3790078:
gameVersion = "1.10";
break;
case 3807424:
gameVersion = "1.11";
break;
case 3825894:
gameVersion = "2.1";
break;
default:
gameVersion = defaultGameVersion;
break;
}
log("[VERSION] Engine build: $engineVersionBuild");
gameVersion = _buildToGameVersion[engineVersionBuild] ?? defaultGameVersion;
}
log("[VERSION] Returning $gameVersion");
return gameVersion;
}
}
@@ -272,5 +378,6 @@ Future<String> extractGameVersion(String filePath, String defaultGameVersion) =>
calloc.free(pv);
}
log("[VERSION] Using default value");
return defaultGameVersion;
});