Release 9.2.0

This commit is contained in:
Alessandro Autiero
2024-07-06 18:43:52 +02:00
parent 45b8629207
commit e3b8d7d182
91 changed files with 3871 additions and 3132 deletions

View File

@@ -26,6 +26,7 @@ Future<bool> isBackendPortFree() async => await pingBackend(kDefaultBackendHost,
Future<bool> freeBackendPort() async {
await killProcessByPort(kDefaultBackendPort);
await killProcessByPort(kDefaultXmppPort);
final standardResult = await isBackendPortFree();
if(standardResult) {
return true;
@@ -35,21 +36,24 @@ Future<bool> freeBackendPort() async {
}
Future<Uri?> pingBackend(String host, int port, [bool https=false]) async {
var hostName = host.replaceFirst("http://", "").replaceFirst("https://", "");
var declaredScheme = host.startsWith("http://") ? "http" : host.startsWith("https://") ? "https" : null;
final hostName = host.replaceFirst("http://", "").replaceFirst("https://", "");
final declaredScheme = host.startsWith("http://") ? "http" : host.startsWith("https://") ? "https" : null;
try{
var uri = Uri(
final uri = Uri(
scheme: declaredScheme ?? (https ? "https" : "http"),
host: hostName,
port: port,
path: "unknown"
);
var client = HttpClient()
..connectionTimeout = const Duration(seconds: 5);
var request = await client.getUrl(uri);
var response = await request.close();
return response.statusCode == 200 || response.statusCode == 404 ? uri : null;
}catch(_){
log("[BACKEND] Pinging $uri...");
final client = HttpClient()
..connectionTimeout = const Duration(seconds: 10);
final request = await client.getUrl(uri);
await request.close().timeout(const Duration(seconds: 10));
log("[BACKEND] Ping successful");
return uri;
}catch(error){
log("[BACKEND] Cannot ping backend: $error");
return https || declaredScheme != null || isLocalHost(host) ? null : await pingBackend(host, port, true);
}
}
@@ -59,16 +63,16 @@ Stream<String?> watchMatchmakingIp() async* {
return;
}
var observer = matchmakerConfigFile.parent.watch(events: FileSystemEvent.modify);
final observer = matchmakerConfigFile.parent.watch(events: FileSystemEvent.modify);
yield* observer.where((event) => event.path == matchmakerConfigFile.path).asyncMap((event) async {
try {
var config = Config.fromString(await matchmakerConfigFile.readAsString());
var ip = config.get("GameServer", "ip");
final config = Config.fromString(await matchmakerConfigFile.readAsString());
final ip = config.get("GameServer", "ip");
if(ip == null) {
return null;
}
var port = config.get("GameServer", "port");
final port = config.get("GameServer", "port");
if(port == null) {
return null;
}
@@ -89,14 +93,14 @@ Stream<String?> watchMatchmakingIp() async* {
}
Future<void> writeMatchmakingIp(String text) async {
var exists = await matchmakerConfigFile.exists();
final exists = await matchmakerConfigFile.exists();
if(!exists) {
return;
}
_semaphore.acquire();
var splitIndex = text.indexOf(":");
var ip = splitIndex != -1 ? text.substring(0, splitIndex) : text;
final splitIndex = text.indexOf(":");
final ip = splitIndex != -1 ? text.substring(0, splitIndex) : text;
var port = splitIndex != -1 ? text.substring(splitIndex + 1) : kDefaultGameServerPort;
if(port.isBlank) {
port = kDefaultGameServerPort;
@@ -104,7 +108,7 @@ Future<void> writeMatchmakingIp(String text) async {
_lastIp = ip;
_lastPort = port;
var config = Config.fromString(await matchmakerConfigFile.readAsString());
final config = Config.fromString(await matchmakerConfigFile.readAsString());
config.set("GameServer", "ip", ip);
config.set("GameServer", "port", port);
await matchmakerConfigFile.writeAsString(config.toString(), flush: true);

View File

@@ -8,6 +8,7 @@ import 'package:dio/io.dart';
import 'package:path/path.dart' as path;
import 'package:reboot_common/common.dart';
import 'package:reboot_common/src/extension/types.dart';
import 'package:version/version.dart';
const String kStopBuildDownloadSignal = "kill";
@@ -23,7 +24,7 @@ Dio _buildDioInstance() {
return dio;
}
final String _archiveSourceUrl = "http://185.203.216.3/versions.json";
final String _archiveSourceUrl = "https://raw.githubusercontent.com/simplyblk/Fortnitebuilds/main/README.md";
final RegExp _rarProgressRegex = RegExp("^((100)|(\\d{1,2}(.\\d*)?))%\$");
const String _deniedConnectionError = "The connection was denied: your firewall might be blocking the download";
const String _unavailableError = "The build downloader is not available right now";
@@ -41,15 +42,35 @@ Future<List<FortniteBuild>> fetchBuilds(ignored) async {
return [];
}
final data = jsonDecode(response.data ?? "{}");
var results = <FortniteBuild>[];
for(final entry in data.entries) {
results.add(FortniteBuild(
identifier: entry.key,
version: "${entry.value["title"]} (${entry.key})",
link: entry.value["url"]
));
for (final line in response.data?.split("\n") ?? []) {
if (!line.startsWith("|")) {
continue;
}
var parts = line.substring(1, line.length - 1).split("|");
if (parts.isEmpty) {
continue;
}
var versionName = parts.first.trim();
final separator = versionName.indexOf("-");
if(separator != -1) {
versionName = versionName.substring(0, separator);
}
final link = parts.last.trim();
try {
results.add(FortniteBuild(
version: Version.parse(versionName),
link: link,
available: link.endsWith(".zip") || link.endsWith(".rar")
));
} on FormatException {
// Ignore
}
}
return results;
}

View File

@@ -0,0 +1,29 @@
import 'dart:io';
import 'package:reboot_common/common.dart';
import 'package:sync/semaphore.dart';
final File launcherLogFile = _createLoggingFile();
final Semaphore _semaphore = Semaphore(1);
File _createLoggingFile() {
final file = File("${logsDirectory.path}\\launcher.log");
file.parent.createSync(recursive: true);
if(file.existsSync()) {
file.deleteSync();
}
file.createSync();
return file;
}
void log(String message) async {
try {
await _semaphore.acquire();
print(message);
await launcherLogFile.writeAsString("$message\n", mode: FileMode.append, flush: true);
}catch(error) {
print("[LOGGER_ERROR] An error occurred while logging: $error");
}finally {
_semaphore.release();
}
}

View File

@@ -6,7 +6,7 @@ Directory get installationDirectory =>
Directory get dllsDirectory => Directory("${installationDirectory.path}\\dlls");
Directory get assetsDirectory {
var directory = Directory("${installationDirectory.path}\\data\\flutter_assets\\assets");
final directory = Directory("${installationDirectory.path}\\data\\flutter_assets\\assets");
if(directory.existsSync()) {
return directory;
}

View File

@@ -104,7 +104,7 @@ Future<bool> startElevatedProcess({required String executable, required String a
return shellResult == 1;
}
Future<Process> startProcess({required File executable, List<String>? args, bool useTempBatch = true, bool window = false, String? name}) async {
Future<Process> startProcess({required File executable, List<String>? args, bool useTempBatch = true, bool window = false, String? name, Map<String, String>? environment}) async {
final argsOrEmpty = args ?? [];
if(useTempBatch) {
final tempScriptDirectory = await tempDirectory.createTemp("reboot_launcher_process");
@@ -115,6 +115,7 @@ Future<Process> startProcess({required File executable, List<String>? args, bool
tempScriptFile.path,
[],
workingDirectory: executable.parent.path,
environment: environment,
mode: window ? ProcessStartMode.detachedWithStdio : ProcessStartMode.normal,
runInShell: window
);
@@ -202,6 +203,7 @@ Future<bool> watchProcess(int pid) async {
return await completer.future;
}
// TODO: Template
List<String> createRebootArgs(String username, String password, bool host, GameServerType hostType, bool log, String additionalArgs) {
if(password.isEmpty) {
username = '${_parseUsername(username, host)}@projectreboot.dev';