mirror of
https://github.com/Auties00/Reboot-Launcher.git
synced 2026-01-13 11:12:23 +01:00
10.0.8
This commit is contained in:
@@ -21,8 +21,10 @@ import 'package:reboot_launcher/src/util/matchmaker.dart';
|
||||
import 'package:reboot_launcher/src/util/translations.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import 'hosting_controller.dart';
|
||||
|
||||
class BackendController extends GetxController {
|
||||
static const String storageName = "v2_backend_storage";
|
||||
static const String storageName = "v3_backend_storage";
|
||||
static const PhysicalKeyboardKey _kDefaultConsoleKey = PhysicalKeyboardKey(0x00070041);
|
||||
|
||||
late final GetStorage? _storage;
|
||||
@@ -162,6 +164,14 @@ class BackendController extends GetxController {
|
||||
detached: detached.value,
|
||||
onError: (errorMessage) {
|
||||
stop(interactive: false);
|
||||
Get.find<GameController>()
|
||||
.instance
|
||||
.value
|
||||
?.kill();
|
||||
Get.find<HostingController>()
|
||||
.instance
|
||||
.value
|
||||
?.kill();
|
||||
_showRebootInfoBar(
|
||||
translations.backendErrorMessage,
|
||||
severity: InfoBarSeverity.error,
|
||||
@@ -508,8 +518,7 @@ class BackendController extends GetxController {
|
||||
}else {
|
||||
FlutterClipboard.controlC(decryptedIp);
|
||||
}
|
||||
Get.find<GameController>()
|
||||
.selectedVersion = version;
|
||||
Get.find<GameController>().selectedVersion.value = version;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _showRebootInfoBar(
|
||||
embedded ? translations.joinedServer(author) : translations.copiedIp,
|
||||
duration: infoBarLongDuration,
|
||||
|
||||
@@ -9,11 +9,14 @@ import 'package:reboot_common/common.dart';
|
||||
import 'package:reboot_launcher/main.dart';
|
||||
import 'package:reboot_launcher/src/messenger/info_bar.dart';
|
||||
import 'package:reboot_launcher/src/util/translations.dart';
|
||||
import 'package:reboot_launcher/src/widget/page/settings_page.dart';
|
||||
import 'package:version/version.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:reboot_launcher/src/controller/game_controller.dart';
|
||||
import 'package:reboot_launcher/src/controller/hosting_controller.dart';
|
||||
|
||||
class DllController extends GetxController {
|
||||
static const String storageName = "v2_dll_storage";
|
||||
static const String storageName = "v3_dll_storage";
|
||||
|
||||
late final GetStorage? _storage;
|
||||
late final TextEditingController customGameServerDll;
|
||||
@@ -27,6 +30,7 @@ class DllController extends GetxController {
|
||||
late final RxBool customGameServer;
|
||||
late final RxnInt timestamp;
|
||||
late final Rx<UpdateStatus> status;
|
||||
late final Map<InjectableDll, StreamSubscription?> _subscriptions;
|
||||
|
||||
DllController() {
|
||||
_storage = appWithNoStorage ? null : GetStorage(storageName);
|
||||
@@ -39,15 +43,16 @@ class DllController extends GetxController {
|
||||
final timerIndex = _storage?.read("timer");
|
||||
timer = Rx(timerIndex == null ? UpdateTimer.hour : UpdateTimer.values.elementAt(timerIndex));
|
||||
timer.listen((value) => _storage?.write("timer", value.index));
|
||||
beforeS20Mirror = TextEditingController(text: _storage?.read("update_url") ?? kRebootBelowS20DownloadUrl);
|
||||
beforeS20Mirror.addListener(() => _storage?.write("update_url", beforeS20Mirror.text));
|
||||
aboveS20Mirror = TextEditingController(text: _storage?.read("old_update_url") ?? kRebootAboveS20DownloadUrl);
|
||||
aboveS20Mirror.addListener(() => _storage?.write("new_update_url", aboveS20Mirror.text));
|
||||
beforeS20Mirror = TextEditingController(text: _storage?.read("before_s20_update_url") ?? kRebootBelowS20DownloadUrl);
|
||||
beforeS20Mirror.addListener(() => _storage?.write("before_s20_update_url", beforeS20Mirror.text));
|
||||
aboveS20Mirror = TextEditingController(text: _storage?.read("after_s20_update_url") ?? kRebootAboveS20DownloadUrl);
|
||||
aboveS20Mirror.addListener(() => _storage?.write("after_s20_update_url", aboveS20Mirror.text));
|
||||
status = Rx(UpdateStatus.waiting);
|
||||
customGameServer = RxBool(_storage?.read("custom_game_server") ?? false);
|
||||
customGameServer.listen((value) => _storage?.write("custom_game_server", value));
|
||||
timestamp = RxnInt(_storage?.read("ts"));
|
||||
timestamp.listen((value) => _storage?.write("ts", value));
|
||||
_subscriptions = {};
|
||||
}
|
||||
|
||||
TextEditingController _createController(String key, InjectableDll dll) {
|
||||
@@ -78,6 +83,7 @@ class DllController extends GetxController {
|
||||
try {
|
||||
if(customGameServer.value) {
|
||||
status.value = UpdateStatus.success;
|
||||
_listenToFileEvents(InjectableDll.gameServer);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -88,6 +94,7 @@ class DllController extends GetxController {
|
||||
);
|
||||
if(!needsUpdate) {
|
||||
status.value = UpdateStatus.success;
|
||||
_listenToFileEvents(InjectableDll.gameServer);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -116,6 +123,7 @@ class DllController extends GetxController {
|
||||
duration: infoBarShortDuration
|
||||
);
|
||||
}
|
||||
_listenToFileEvents(InjectableDll.gameServer);
|
||||
return true;
|
||||
}catch(message) {
|
||||
infoBarEntry?.close();
|
||||
@@ -123,26 +131,29 @@ class DllController extends GetxController {
|
||||
error = error.contains(": ") ? error.substring(error.indexOf(": ") + 2) : error;
|
||||
error = error.toLowerCase();
|
||||
status.value = UpdateStatus.error;
|
||||
final completer = Completer<bool>();
|
||||
infoBarEntry = showRebootInfoBar(
|
||||
translations.downloadDllError(error.toString(), "reboot.dll"),
|
||||
duration: infoBarLongDuration,
|
||||
severity: InfoBarSeverity.error,
|
||||
onDismissed: () => completer.complete(false),
|
||||
action: Button(
|
||||
onPressed: () async {
|
||||
infoBarEntry?.close();
|
||||
updateGameServerDll(
|
||||
final result = updateGameServerDll(
|
||||
force: true,
|
||||
silent: silent
|
||||
);
|
||||
completer.complete(result);
|
||||
},
|
||||
child: Text(translations.downloadDllRetry),
|
||||
)
|
||||
);
|
||||
return false;
|
||||
return completer.future;
|
||||
}
|
||||
}
|
||||
|
||||
(File, bool) getInjectableData(Version version, InjectableDll dll) {
|
||||
(File, bool) getInjectableData(String version, InjectableDll dll) {
|
||||
final defaultPath = canonicalize(getDefaultDllPath(dll));
|
||||
switch(dll){
|
||||
case InjectableDll.gameServer:
|
||||
@@ -150,7 +161,7 @@ class DllController extends GetxController {
|
||||
return (File(customGameServerDll.text), true);
|
||||
}
|
||||
|
||||
return (version.major >= 20 ? rebootAboveS20DllFile : rebootBeforeS20DllFile, false);
|
||||
return (_isS20(version) ? rebootAboveS20DllFile : rebootBeforeS20DllFile, false);
|
||||
case InjectableDll.console:
|
||||
final ue4ConsoleFile = File(unrealEngineConsoleDll.text);
|
||||
return (ue4ConsoleFile, canonicalize(ue4ConsoleFile.path) != defaultPath);
|
||||
@@ -163,6 +174,14 @@ class DllController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
bool _isS20(String version) {
|
||||
try {
|
||||
return Version.parse(version).major >= 20;
|
||||
} on FormatException catch(_) {
|
||||
return version.trim().startsWith("20.");
|
||||
}
|
||||
}
|
||||
|
||||
TextEditingController getDllEditingController(InjectableDll dll) {
|
||||
switch(dll) {
|
||||
case InjectableDll.console:
|
||||
@@ -177,16 +196,16 @@ class DllController extends GetxController {
|
||||
}
|
||||
|
||||
String getDefaultDllPath(InjectableDll dll) {
|
||||
switch(dll) {
|
||||
case InjectableDll.console:
|
||||
return "${dllsDirectory.path}\\console.dll";
|
||||
case InjectableDll.auth:
|
||||
return "${dllsDirectory.path}\\cobalt.dll";
|
||||
case InjectableDll.gameServer:
|
||||
return "${dllsDirectory.path}\\reboot.dll";
|
||||
case InjectableDll.memoryLeak:
|
||||
return "${dllsDirectory.path}\\memory.dll";
|
||||
}
|
||||
switch(dll) {
|
||||
case InjectableDll.console:
|
||||
return "${dllsDirectory.path}\\console.dll";
|
||||
case InjectableDll.auth:
|
||||
return "${dllsDirectory.path}\\cobalt.dll";
|
||||
case InjectableDll.gameServer:
|
||||
return "${dllsDirectory.path}\\reboot.dll";
|
||||
case InjectableDll.memoryLeak:
|
||||
return "${dllsDirectory.path}\\memory.dll";
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> download(InjectableDll dll, String filePath, {bool silent = false, bool force = false}) async {
|
||||
@@ -198,77 +217,136 @@ class DllController extends GetxController {
|
||||
}
|
||||
|
||||
if(!force && File(filePath).existsSync()) {
|
||||
log("[DLL] File already exists");
|
||||
log("[DLL] $dll already exists");
|
||||
_listenToFileEvents(dll);
|
||||
return true;
|
||||
}
|
||||
|
||||
log("[DLL] Downloading $dll...");
|
||||
final fileNameWithoutExtension = basenameWithoutExtension(filePath);
|
||||
if(!silent) {
|
||||
log("[DLL] Showing dialog while downloading $dll...");
|
||||
entry = showRebootInfoBar(
|
||||
translations.downloadingDll(fileNameWithoutExtension),
|
||||
loading: true,
|
||||
duration: null
|
||||
);
|
||||
}else {
|
||||
log("[DLL] Not showing dialog while downloading $dll...");
|
||||
}
|
||||
await downloadDependency(dll, filePath);
|
||||
final result = await downloadDependency(dll, filePath);
|
||||
if(!result) {
|
||||
entry?.close();
|
||||
showRebootInfoBar(
|
||||
translations.downloadDllAntivirus(antiVirusName ?? defaultAntiVirusName, dll.name),
|
||||
duration: infoBarLongDuration,
|
||||
severity: InfoBarSeverity.error
|
||||
);
|
||||
return false;
|
||||
}
|
||||
log("[DLL] Downloaded $dll");
|
||||
entry?.close();
|
||||
if(!silent) {
|
||||
log("[DLL] Showing success dialog for $dll");
|
||||
entry = await showRebootInfoBar(
|
||||
translations.downloadDllSuccess(fileNameWithoutExtension),
|
||||
severity: InfoBarSeverity.success,
|
||||
duration: infoBarShortDuration
|
||||
);
|
||||
}else {
|
||||
log("[DLL] Not showing success dialog for $dll");
|
||||
}
|
||||
_listenToFileEvents(dll);
|
||||
return true;
|
||||
}catch(message) {
|
||||
log("[DLL] Error: $message");
|
||||
log("[DLL] An error occurred while downloading $dll: $message");
|
||||
entry?.close();
|
||||
var error = message.toString();
|
||||
error =
|
||||
error.contains(": ") ? error.substring(error.indexOf(": ") + 2) : error;
|
||||
error = error.contains(": ") ? error.substring(error.indexOf(": ") + 2) : error;
|
||||
error = error.toLowerCase();
|
||||
final completer = Completer();
|
||||
final completer = Completer<bool>();
|
||||
await showRebootInfoBar(
|
||||
translations.downloadDllError(error.toString(), dll.name),
|
||||
duration: infoBarLongDuration,
|
||||
severity: InfoBarSeverity.error,
|
||||
onDismissed: () => completer.complete(null),
|
||||
onDismissed: () => completer.complete(false),
|
||||
action: Button(
|
||||
onPressed: () async {
|
||||
await download(dll, filePath, silent: silent, force: force);
|
||||
completer.complete(null);
|
||||
final result = await download(dll, filePath, silent: silent, force: force);
|
||||
completer.complete(result);
|
||||
},
|
||||
child: Text(translations.downloadDllRetry),
|
||||
)
|
||||
);
|
||||
await completer.future;
|
||||
return false;
|
||||
return completer.future;
|
||||
}
|
||||
}
|
||||
|
||||
void guardFiles() {
|
||||
Future<void> downloadAndGuardDependencies() async {
|
||||
for(final injectable in InjectableDll.values) {
|
||||
final controller = getDllEditingController(injectable);
|
||||
final defaultPath = getDefaultDllPath(injectable);
|
||||
if (path.equals(controller.text, defaultPath)) {
|
||||
download(injectable, controller.text);
|
||||
}
|
||||
controller.addListener(() async {
|
||||
try {
|
||||
if (!path.equals(controller.text, defaultPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final filePath = controller.text;
|
||||
await for(final event in File(filePath).parent.watch(events: FileSystemEvent.delete | FileSystemEvent.move)) {
|
||||
if (path.equals(event.path, filePath)) {
|
||||
await download(injectable, filePath);
|
||||
}
|
||||
}
|
||||
} catch(_) {
|
||||
// Ignore
|
||||
}
|
||||
});
|
||||
if(path.equals(controller.text, defaultPath)) {
|
||||
await download(injectable, controller.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _listenToFileEvents(InjectableDll injectable) {
|
||||
final controller = getDllEditingController(injectable);
|
||||
final defaultPath = getDefaultDllPath(injectable);
|
||||
|
||||
void onFileEvent(FileSystemEvent event, String filePath) {
|
||||
if (!path.equals(event.path, filePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(path.equals(filePath, defaultPath)) {
|
||||
Get.find<GameController>()
|
||||
.instance
|
||||
.value
|
||||
?.kill();
|
||||
Get.find<HostingController>()
|
||||
.instance
|
||||
.value
|
||||
?.kill();
|
||||
showRebootInfoBar(
|
||||
translations.downloadDllAntivirus(antiVirusName ?? defaultAntiVirusName, injectable.name),
|
||||
duration: infoBarLongDuration,
|
||||
severity: InfoBarSeverity.error
|
||||
);
|
||||
}
|
||||
|
||||
_updateInput(injectable);
|
||||
}
|
||||
|
||||
StreamSubscription subscribe(String filePath) => File(filePath)
|
||||
.parent
|
||||
.watch(events: FileSystemEvent.delete | FileSystemEvent.move)
|
||||
.listen((event) => onFileEvent(event, filePath));
|
||||
|
||||
controller.addListener(() {
|
||||
_subscriptions[injectable]?.cancel();
|
||||
_subscriptions[injectable] = subscribe(controller.text);
|
||||
});
|
||||
_subscriptions[injectable] = subscribe(controller.text);
|
||||
}
|
||||
|
||||
void _updateInput(InjectableDll injectable) {
|
||||
switch(injectable) {
|
||||
case InjectableDll.console:
|
||||
settingsConsoleDllInputKey.currentState?.validate();
|
||||
break;
|
||||
case InjectableDll.auth:
|
||||
settingsAuthDllInputKey.currentState?.validate();
|
||||
break;
|
||||
case InjectableDll.gameServer:
|
||||
settingsGameServerDllInputKey.currentState?.validate();
|
||||
break;
|
||||
case InjectableDll.memoryLeak:
|
||||
settingsMemoryDllInputKey.currentState?.validate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -8,14 +9,14 @@ import 'package:reboot_common/common.dart';
|
||||
import 'package:reboot_launcher/main.dart';
|
||||
|
||||
class GameController extends GetxController {
|
||||
static const String storageName = "v2_game_storage";
|
||||
static const String storageName = "v3_game_storage";
|
||||
|
||||
late final GetStorage? _storage;
|
||||
late final TextEditingController username;
|
||||
late final TextEditingController password;
|
||||
late final TextEditingController customLaunchArgs;
|
||||
late final Rx<List<FortniteVersion>> versions;
|
||||
late final Rxn<FortniteVersion> _selectedVersion;
|
||||
late final Rxn<FortniteVersion> selectedVersion;
|
||||
late final RxBool started;
|
||||
late final Rxn<GameInstance> instance;
|
||||
|
||||
@@ -28,8 +29,8 @@ class GameController extends GetxController {
|
||||
versions = Rx(decodedVersions);
|
||||
versions.listen((data) => _saveVersions());
|
||||
final decodedSelectedVersionName = _storage?.read("version");
|
||||
final decodedSelectedVersion = decodedVersions.firstWhereOrNull((element) => element.content.toString() == decodedSelectedVersionName);
|
||||
_selectedVersion = Rxn(decodedSelectedVersion);
|
||||
selectedVersion = Rxn(decodedVersions.firstWhereOrNull((element) => element.name == decodedSelectedVersionName));
|
||||
selectedVersion.listen((version) => _storage?.write("version", version?.name));
|
||||
username = TextEditingController(
|
||||
text: _storage?.read("username") ?? kDefaultPlayerName);
|
||||
username.addListener(() => _storage?.write("username", username.text));
|
||||
@@ -46,26 +47,27 @@ class GameController extends GetxController {
|
||||
password.text = "";
|
||||
customLaunchArgs.text = "";
|
||||
versions.value = [];
|
||||
_selectedVersion.value = null;
|
||||
selectedVersion.value = null;
|
||||
instance.value = null;
|
||||
}
|
||||
|
||||
FortniteVersion? getVersionByName(String name) {
|
||||
return versions.value.firstWhereOrNull((element) => element.content.toString() == name);
|
||||
name = name.trim();
|
||||
return versions.value.firstWhereOrNull((element) => element.name == name);
|
||||
}
|
||||
|
||||
void addVersion(FortniteVersion version) {
|
||||
var empty = versions.value.isEmpty;
|
||||
versions.update((val) => val?.add(version));
|
||||
if(empty){
|
||||
selectedVersion = version;
|
||||
}
|
||||
selectedVersion.value = version;
|
||||
}
|
||||
|
||||
void removeVersion(FortniteVersion version) {
|
||||
versions.update((val) => val?.remove(version));
|
||||
if (selectedVersion == version || hasNoVersions) {
|
||||
selectedVersion = null;
|
||||
final index = versions.value.indexOf(version);
|
||||
versions.update((val) => val?.removeAt(index));
|
||||
if(hasNoVersions) {
|
||||
selectedVersion.value = null;
|
||||
}else {
|
||||
selectedVersion.value = versions.value.elementAt(max(0, index - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,14 +80,5 @@ class GameController extends GetxController {
|
||||
|
||||
bool get hasNoVersions => versions.value.isEmpty;
|
||||
|
||||
FortniteVersion? get selectedVersion => _selectedVersion();
|
||||
|
||||
set selectedVersion(FortniteVersion? version) {
|
||||
_selectedVersion.value = version;
|
||||
_storage?.write("version", version?.content.toString());
|
||||
}
|
||||
|
||||
void updateVersion(FortniteVersion version, Function(FortniteVersion) function) {
|
||||
versions.update((val) => function(version));
|
||||
}
|
||||
void updateVersion(FortniteVersion version, Function(FortniteVersion) function) => versions.update((val) => function(version));
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'package:sync/semaphore.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class HostingController extends GetxController {
|
||||
static const String storageName = "v2_hosting_storage";
|
||||
static const String storageName = "v3_hosting_storage";
|
||||
|
||||
late final GetStorage? _storage;
|
||||
late final String uuid;
|
||||
@@ -26,7 +26,7 @@ class HostingController extends GetxController {
|
||||
late final FocusNode passwordFocusNode;
|
||||
late final RxBool showPassword;
|
||||
late final RxBool discoverable;
|
||||
late final Rx<GameServerType> type;
|
||||
late final RxBool headless;
|
||||
late final RxBool autoRestart;
|
||||
late final RxBool started;
|
||||
late final RxBool published;
|
||||
@@ -54,8 +54,8 @@ class HostingController extends GetxController {
|
||||
passwordFocusNode = FocusNode();
|
||||
discoverable = RxBool(_storage?.read("discoverable") ?? false);
|
||||
discoverable.listen((value) => _storage?.write("discoverable", value));
|
||||
type = Rx(GameServerType.values.elementAt(_storage?.read("type") ?? GameServerType.headless.index));
|
||||
type.listen((value) => _storage?.write("type", value.index));
|
||||
headless = RxBool(_storage?.read("headless") ?? true);
|
||||
headless.listen((value) => _storage?.write("headless", value));
|
||||
autoRestart = RxBool(_storage?.read("auto_restart") ?? true);
|
||||
autoRestart.listen((value) => _storage?.write("auto_restart", value));
|
||||
started = RxBool(false);
|
||||
@@ -165,7 +165,7 @@ class HostingController extends GetxController {
|
||||
showPassword.value = false;
|
||||
discoverable.value = false;
|
||||
instance.value = null;
|
||||
type.value = GameServerType.headless;
|
||||
headless.value = true;
|
||||
autoRestart.value = true;
|
||||
customLaunchArgs.text = "";
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import 'package:version/version.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
class SettingsController extends GetxController {
|
||||
static const String storageName = "v2_settings_storage";
|
||||
static const String storageName = "v3_settings_storage";
|
||||
|
||||
late final GetStorage? _storage;
|
||||
late final RxString language;
|
||||
|
||||
Reference in New Issue
Block a user